]> Shamusworld >> Repos - ttedit/commitdiff
Set the eol style on the project to native, to avoid line ending chaos.
authorShamus Hammons <jlhamm@acm.org>
Sun, 31 Aug 2008 11:30:09 +0000 (11:30 +0000)
committerShamus Hammons <jlhamm@acm.org>
Sun, 31 Aug 2008 11:30:09 +0000 (11:30 +0000)
37 files changed:
res/cur1.xpm
res/cur2.xpm
res/cur3.xpm
res/cur4.xpm
res/cur5.xpm
res/cur6.xpm
res/cur7.xpm
res/cur8.xpm
res/tool1.xpm
res/tool2.xpm
res/tool3.xpm
res/toolpal1.xpm
src/charnames.cpp
src/charnames.h
src/charwindow.cpp
src/charwindow.h
src/debug.cpp
src/debug.h
src/editwindow.cpp
src/editwindow.h
src/glyphpoints.cpp
src/glyphpoints.h
src/graphicprimitives.cpp
src/graphicprimitives.h
src/list.h
src/registry.cpp
src/registry.h
src/toolwindow.cpp
src/toolwindow.h
src/tte_res.h
src/ttedit.cpp
src/ttedit.h
src/ttf.cpp
src/ttf.h
src/types.h
src/vector.cpp
src/vector.h

index b69ef60fac07caf8c473ae79e71d095faa8df8a6..2d4038c303bc443055a5010fb99459e5821e6e42 100755 (executable)
@@ -1,37 +1,37 @@
-/* XPM */\r
-static const char * cur1_xpm[] = {\r
-"32 32 2 1",\r
-"      g #000000",\r
-".     g #FFFFFF",\r
-" ...............................",\r
-"  ..............................",\r
-"   .............................",\r
-"    ............................",\r
-"     ...........................",\r
-"      ..........................",\r
-"       .........................",\r
-"        ........................",\r
-"         .......................",\r
-"          ......................",\r
-"           .....................",\r
-"            ....................",\r
-"       .........................",\r
-"       .........................",\r
-"   ..   ........................",\r
-"  ...   ........................",\r
-" .....   .......................",\r
-"......   .......................",\r
-".......   ......................",\r
-".......  .......................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................"};\r
+/* XPM */
+static const char * cur1_xpm[] = {
+"32 32 2 1",
+"      g #000000",
+".     g #FFFFFF",
+" ...............................",
+"  ..............................",
+"   .............................",
+"    ............................",
+"     ...........................",
+"      ..........................",
+"       .........................",
+"        ........................",
+"         .......................",
+"          ......................",
+"           .....................",
+"            ....................",
+"       .........................",
+"       .........................",
+"   ..   ........................",
+"  ...   ........................",
+" .....   .......................",
+"......   .......................",
+".......   ......................",
+".......  .......................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
index 956ddf4987f2b79457d14522e3350d884a48af07..446c74bdb3f3e81490a32e7f3f254621a25809b7 100755 (executable)
@@ -1,37 +1,37 @@
-/* XPM */\r
-static const char * cur2_xpm[] = {\r
-"32 32 2 1",\r
-"      g #000000",\r
-".     g #FFFFFF",\r
-" ...............................",\r
-"  ..............................",\r
-"   .............................",\r
-"    ............................",\r
-"     ...........................",\r
-"      ..........................",\r
-"       .........................",\r
-"        ........................",\r
-"         .......................",\r
-"          ......................",\r
-"           .....................",\r
-"            ....................",\r
-"       .........................",\r
-"       ......      .............",\r
-"   ..   .....       ............",\r
-"  ...   .....  ...  ............",\r
-" .....   ....  ...  ............",\r
-"......   ....  ...  ............",\r
-".......   ...       ............",\r
-".......  ....      .............",\r
-".............  .................",\r
-".............  .................",\r
-".............  .................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................"};\r
+/* XPM */
+static const char * cur2_xpm[] = {
+"32 32 2 1",
+"      g #000000",
+".     g #FFFFFF",
+" ...............................",
+"  ..............................",
+"   .............................",
+"    ............................",
+"     ...........................",
+"      ..........................",
+"       .........................",
+"        ........................",
+"         .......................",
+"          ......................",
+"           .....................",
+"            ....................",
+"       .........................",
+"       ......      .............",
+"   ..   .....       ............",
+"  ...   .....  ...  ............",
+" .....   ....  ...  ............",
+"......   ....  ...  ............",
+".......   ...       ............",
+".......  ....      .............",
+".............  .................",
+".............  .................",
+".............  .................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
index 881e009b94633f80e23a99ecfc0f577e10a7beb7..b920e6bc8d836fed7c184b29c11d94e0496e33c3 100755 (executable)
@@ -1,37 +1,37 @@
-/* XPM */\r
-static const char * cur3_xpm[] = {\r
-"32 32 2 1",\r
-"      g #FFFFFF",\r
-".     g #000000",\r
-"          ..                    ",\r
-"          ..                    ",\r
-"         ....                   ",\r
-"         ....                   ",\r
-"        ......                  ",\r
-"        . .. .                  ",\r
-"      .   ..   .                ",\r
-"          ..                    ",\r
-"    ..    ..    ..              ",\r
-"  ...    .  .    ...            ",\r
-"......... .. .........          ",\r
-"......... .. .........          ",\r
-"  ...    .  .    ...            ",\r
-"    ..    ..    ..              ",\r
-"          ..                    ",\r
-"      .   ..   .                ",\r
-"        . .. .                  ",\r
-"        ......                  ",\r
-"        .....                   ",\r
-"         ....                   ",\r
-"          ..                    ",\r
-"          ..                    ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                ",\r
-"                                "};\r
+/* XPM */
+static const char * cur3_xpm[] = {
+"32 32 2 1",
+"      g #FFFFFF",
+".     g #000000",
+"          ..                    ",
+"          ..                    ",
+"         ....                   ",
+"         ....                   ",
+"        ......                  ",
+"        . .. .                  ",
+"      .   ..   .                ",
+"          ..                    ",
+"    ..    ..    ..              ",
+"  ...    .  .    ...            ",
+"......... .. .........          ",
+"......... .. .........          ",
+"  ...    .  .    ...            ",
+"    ..    ..    ..              ",
+"          ..                    ",
+"      .   ..   .                ",
+"        . .. .                  ",
+"        ......                  ",
+"        .....                   ",
+"         ....                   ",
+"          ..                    ",
+"          ..                    ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "};
index d4fec81772a64040a70c01d0a9cbfd8b23ad6629..a7527c72487bd32ed53101bce41e3953ffd20b6d 100755 (executable)
@@ -1,37 +1,37 @@
-/* XPM */\r
-static const char * cur4_xpm[] = {\r
-"32 32 2 1",\r
-"      g #FFFFFF",\r
-".     g #000000",\r
-"  ..                            ",\r
-"  ..                            ",\r
-"......                          ",\r
-"......                          ",\r
-"  ..                            ",\r
-"  ..                            ",\r
-"             ...                ",\r
-"  ..       ..   ..              ",\r
-"  ..      ..     ..             ",\r
-" ....     .  .    .             ",\r
-" ....    .  .      .            ",\r
-"......   . .       .            ",\r
-". .. .   . .       .            ",\r
-"  ..     .         .            ",\r
-"  ..     .         .            ",\r
-"  ..      .       .             ",\r
-"  ..      ..     ..             ",\r
-"  ..       ..   ...             ",\r
-"  ..         ...   .            ",\r
-". .. .              .           ",\r
-"......               ..         ",\r
-" ....                ...        ",\r
-" ....                 ...       ",\r
-"  ..                   ...      ",\r
-"  ..                    .       ",\r
-"                                ",\r
-"                                ",\r
-"......                          ",\r
-"......                          ",\r
-"                                ",\r
-"                                ",\r
-"                                "};\r
+/* XPM */
+static const char * cur4_xpm[] = {
+"32 32 2 1",
+"      g #FFFFFF",
+".     g #000000",
+"  ..                            ",
+"  ..                            ",
+"......                          ",
+"......                          ",
+"  ..                            ",
+"  ..                            ",
+"             ...                ",
+"  ..       ..   ..              ",
+"  ..      ..     ..             ",
+" ....     .  .    .             ",
+" ....    .  .      .            ",
+"......   . .       .            ",
+". .. .   . .       .            ",
+"  ..     .         .            ",
+"  ..     .         .            ",
+"  ..      .       .             ",
+"  ..      ..     ..             ",
+"  ..       ..   ...             ",
+"  ..         ...   .            ",
+". .. .              .           ",
+"......               ..         ",
+" ....                ...        ",
+" ....                 ...       ",
+"  ..                   ...      ",
+"  ..                    .       ",
+"                                ",
+"                                ",
+"......                          ",
+"......                          ",
+"                                ",
+"                                ",
+"                                "};
index cebcfc5ce9c14b24f327bd2c6c0f258488466c64..8620aaf3677b95e7eb6321c0bb04238a7826a98a 100755 (executable)
@@ -1,37 +1,37 @@
-/* XPM */\r
-static const char * cur5_xpm[] = {\r
-"32 32 2 1",\r
-"      g #000000",\r
-".     g #FFFFFF",\r
-" ...............................",\r
-"  ..............................",\r
-"   .............................",\r
-"    ............................",\r
-"     ...........................",\r
-"      ..........................",\r
-"       .........................",\r
-"        ........................",\r
-"         .......................",\r
-"          ......................",\r
-"           .....................",\r
-"            ....................",\r
-"       .........................",\r
-"       ...... ..................",\r
-"   ..   ....   .................",\r
-"  ...   ..... ..................",\r
-" .....   .......................",\r
-"......   .....    ..............",\r
-".......   ...      .............",\r
-".......  ....  ..  .............",\r
-".............  ..  .............",\r
-".............      .............",\r
-"..............    ..............",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................"};\r
+/* XPM */
+static const char * cur5_xpm[] = {
+"32 32 2 1",
+"      g #000000",
+".     g #FFFFFF",
+" ...............................",
+"  ..............................",
+"   .............................",
+"    ............................",
+"     ...........................",
+"      ..........................",
+"       .........................",
+"        ........................",
+"         .......................",
+"          ......................",
+"           .....................",
+"            ....................",
+"       .........................",
+"       ...... ..................",
+"   ..   ....   .................",
+"  ...   ..... ..................",
+" .....   .......................",
+"......   .....    ..............",
+".......   ...      .............",
+".......  ....  ..  .............",
+".............  ..  .............",
+".............      .............",
+"..............    ..............",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
index e0f44c7e974e8edf3468f6219b7fbd364a4f47ac..018918e6e81c3e6681cebcbaa413f8a9cd20e589 100755 (executable)
@@ -1,37 +1,37 @@
-/* XPM */\r
-static const char * cur6_xpm[] = {\r
-"32 32 2 1",\r
-"      g #000000",\r
-".     g #FFFFFF",\r
-" ...............................",\r
-"  ..............................",\r
-"   .............................",\r
-"    ............................",\r
-"     ...........................",\r
-"      ..........................",\r
-"       .........................",\r
-"        ........................",\r
-"         .......................",\r
-"          ......................",\r
-"           .....................",\r
-"            ....................",\r
-"       ........  ...............",\r
-"       .......    ..............",\r
-"   ..   ......    ..............",\r
-"  ...   .....  ..  .............",\r
-" .....   ....  ..  .............",\r
-"......   ...  ....  ............",\r
-".......   ..  ....  ............",\r
-".......  ..  ......  ...........",\r
-"...........  ......  ...........",\r
-"..........  ........  ..........",\r
-"..........            ..........",\r
-"...........          ...........",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................"};\r
+/* XPM */
+static const char * cur6_xpm[] = {
+"32 32 2 1",
+"      g #000000",
+".     g #FFFFFF",
+" ...............................",
+"  ..............................",
+"   .............................",
+"    ............................",
+"     ...........................",
+"      ..........................",
+"       .........................",
+"        ........................",
+"         .......................",
+"          ......................",
+"           .....................",
+"            ....................",
+"       ........  ...............",
+"       .......    ..............",
+"   ..   ......    ..............",
+"  ...   .....  ..  .............",
+" .....   ....  ..  .............",
+"......   ...  ....  ............",
+".......   ..  ....  ............",
+".......  ..  ......  ...........",
+"...........  ......  ...........",
+"..........  ........  ..........",
+"..........            ..........",
+"...........          ...........",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
index 0f7d04d919f42bd3d8357e389d58a6313565da1c..6dd57b7e5fb104cff0f5965991420479a5b2af2f 100755 (executable)
@@ -1,37 +1,37 @@
-/* XPM */\r
-static const char * cur7_xpm[] = {\r
-"32 32 2 1",\r
-"      g #000000",\r
-".     g #FFFFFF",\r
-" ...............................",\r
-"  ..............................",\r
-"   .............................",\r
-"    ............................",\r
-"     ...........................",\r
-"      ..........................",\r
-"       .........................",\r
-"        ........................",\r
-"         .......................",\r
-"          ......................",\r
-"           .....................",\r
-"            ....................",\r
-"       .........................",\r
-"       .........................",\r
-"   ..   ........................",\r
-"  ...   ...  ......  ...........",\r
-" .....   ..   ....   ...........",\r
-"......   ...        ............",\r
-".......   ...      .............",\r
-".......  ....      .............",\r
-".............      .............",\r
-".............      .............",\r
-"............        ............",\r
-"...........   ....   ...........",\r
-"...........  ......  ...........",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................"};\r
+/* XPM */
+static const char * cur7_xpm[] = {
+"32 32 2 1",
+"      g #000000",
+".     g #FFFFFF",
+" ...............................",
+"  ..............................",
+"   .............................",
+"    ............................",
+"     ...........................",
+"      ..........................",
+"       .........................",
+"        ........................",
+"         .......................",
+"          ......................",
+"           .....................",
+"            ....................",
+"       .........................",
+"       .........................",
+"   ..   ........................",
+"  ...   ...  ......  ...........",
+" .....   ..   ....   ...........",
+"......   ...        ............",
+".......   ...      .............",
+".......  ....      .............",
+".............      .............",
+".............      .............",
+"............        ............",
+"...........   ....   ...........",
+"...........  ......  ...........",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
index edb642264ef09819336d26f5f3a32e035f00afd7..37861290fa1e27589e7a91d251e70dc6a1033c39 100755 (executable)
@@ -1,37 +1,37 @@
-/* XPM */\r
-static const char * cur8_xpm[] = {\r
-"32 32 2 1",\r
-"      g #000000",\r
-".     g #FFFFFF",\r
-" ...............................",\r
-"  ..............................",\r
-"   .............................",\r
-"    ............................",\r
-"     ...........................",\r
-"      ..........................",\r
-"       .........................",\r
-"        ........................",\r
-"         .......................",\r
-"          ......................",\r
-"           .....................",\r
-"            ....................",\r
-"       .........................",\r
-"       .........................",\r
-"   ..   ........................",\r
-"  ...   ...  ......  ...........",\r
-" .....   ..   ....   ...........",\r
-"......   ...        ............",\r
-".......   ...      .............",\r
-".......  ....      .............",\r
-".............      .............",\r
-".............      .............",\r
-"............        ............",\r
-"...........   ....   ...........",\r
-"...........  ......  ...........",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................",\r
-"................................"};\r
+/* XPM */
+static const char * cur8_xpm[] = {
+"32 32 2 1",
+"      g #000000",
+".     g #FFFFFF",
+" ...............................",
+"  ..............................",
+"   .............................",
+"    ............................",
+"     ...........................",
+"      ..........................",
+"       .........................",
+"        ........................",
+"         .......................",
+"          ......................",
+"           .....................",
+"            ....................",
+"       .........................",
+"       .........................",
+"   ..   ........................",
+"  ...   ...  ......  ...........",
+" .....   ..   ....   ...........",
+"......   ...        ............",
+".......   ...      .............",
+".......  ....      .............",
+".............      .............",
+".............      .............",
+"............        ............",
+"...........   ....   ...........",
+"...........  ......  ...........",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
index a0703fd7d91bd39fc4141a4beba4c452c4b6ad51..214f4f8003a0c54ac434b673a069a7f38151f856 100755 (executable)
@@ -1,21 +1,21 @@
-/* XPM */\r
-static const char * tool1_xpm[] = {\r
-"16 15 3 1",\r
-"      c None",\r
-".     c #A0A0A0",\r
-"+     c #000000",\r
-"                ",\r
-"                ",\r
-"                ",\r
-"                ",\r
-"      ++        ",\r
-"     ++         ",\r
-"   ++++         ",\r
-" ++++++++++++++ ",\r
-"   ++++         ",\r
-"     ++         ",\r
-"      ++        ",\r
-"                ",\r
-"                ",\r
-"                ",\r
-"                "};\r
+/* XPM */
+static const char * tool1_xpm[] = {
+"16 15 3 1",
+"      c None",
+".     c #A0A0A0",
+"+     c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"      ++        ",
+"     ++         ",
+"   ++++         ",
+" ++++++++++++++ ",
+"   ++++         ",
+"     ++         ",
+"      ++        ",
+"                ",
+"                ",
+"                ",
+"                "};
index e73fc450f4d603cb5de60404a7a75aa7bcf80eb8..465c680767668691493a4d82af7025b765cd4fd1 100755 (executable)
@@ -1,21 +1,21 @@
-/* XPM */\r
-static const char * tool2_xpm[] = {\r
-"16 15 3 1",\r
-"      c None",\r
-".     c #C0C0C0",\r
-"+     c #000000",\r
-"                ",\r
-"                ",\r
-"                ",\r
-"                ",\r
-"        ++      ",\r
-"         ++     ",\r
-"         ++++   ",\r
-" ++++++++++++++ ",\r
-"         ++++   ",\r
-"         ++     ",\r
-"        ++      ",\r
-"                ",\r
-"                ",\r
-"                ",\r
-"                "};\r
+/* XPM */
+static const char * tool2_xpm[] = {
+"16 15 3 1",
+"      c None",
+".     c #C0C0C0",
+"+     c #000000",
+"                ",
+"                ",
+"                ",
+"                ",
+"        ++      ",
+"         ++     ",
+"         ++++   ",
+" ++++++++++++++ ",
+"         ++++   ",
+"         ++     ",
+"        ++      ",
+"                ",
+"                ",
+"                ",
+"                "};
index 885a87027b0280f8cd0f405a40554c82e325ced2..397668e54b8338749da040f9ca9bdf0f224f4d89 100755 (executable)
@@ -1,22 +1,22 @@
-/* XPM */\r
-static const char * tool3_xpm[] = {\r
-"16 15 3 1",\r
-"      c None",\r
-".     c #C0C0C0",\r
-"+     c #000000",\r
-"++++++++++++++++",\r
-"+              +",\r
-"+   ++++++++   +",\r
-"+  ++++++++++  +",\r
-"+  ++      ++  +",\r
-"+          ++  +",\r
-"+   +++++++++  +",\r
-"+  ++++++++++  +",\r
-"+  ++      ++  +",\r
-"+  ++      ++  +",\r
-"+  ++     +++  +",\r
-"+  ++++++++++  +",\r
-"+   ++++++  ++ +",\r
-"+              +",\r
-"++++++++++++++++"};\r
-\r
+/* XPM */
+static const char * tool3_xpm[] = {
+"16 15 3 1",
+"      c None",
+".     c #C0C0C0",
+"+     c #000000",
+"++++++++++++++++",
+"+              +",
+"+   ++++++++   +",
+"+  ++++++++++  +",
+"+  ++      ++  +",
+"+          ++  +",
+"+   +++++++++  +",
+"+  ++++++++++  +",
+"+  ++      ++  +",
+"+  ++      ++  +",
+"+  ++     +++  +",
+"+  ++++++++++  +",
+"+   ++++++  ++ +",
+"+              +",
+"++++++++++++++++"};
+
index 5f29c6de50f9fd43775b013aa96bc4e65f9d46b6..f6f329f6ea5deb7740befc4d29ee2e108985e158 100755 (executable)
@@ -1,53 +1,53 @@
-/* XPM */\r
-static const char * toolpal1_xpm[] = {\r
-"96 48 2 1",\r
-"      c #000000",\r
-".     c #FFFFFF",\r
-"                                                                                                ",\r
-"   ..................      ..................      ..................      ..................   ",\r
-"                                                                                                ",\r
-" . .................. .  . .................. .  . .................. .  . .................. . ",\r
-" . .... ............. .  . .................. .  . ........  ........ .  . .................. . ",\r
-" . ....  ............ .  . .................. .  . ........  ........ .  . ......  .......... . ",\r
-" . ....   ........... .  . .. ............... .  . .......    ....... .  . ....  ..  ........ . ",\r
-" . ....    .......... .  . ..  .............. .  . .......    ....... .  . ... ...... ....... . ",\r
-" . ....     ......... .  . ..   ............. .  . ...... .  . ...... .  . ... ...... ....... . ",\r
-" . ....      ........ .  . ..    ............ .  . ..... ..  .. ..... .  . .. ........ ...... . ",\r
-" . ....       ....... .  . ..     ...      .. .  . ...  ...  ...  ... .  . .. ........ ...... . ",\r
-" . ....        ...... .  . ..      ..       . .  . .                . .  . ... ...... ....... . ",\r
-" . ....         ..... .  . ..       .  ...  . .  . .                . .  . ... ...... ....... . ",\r
-" . ....      ........ .  . ..     ...  ...  . .  . ...  ...  ...  ... .  . ....  ..    ...... . ",\r
-" . ....      ........ .  . ..     ...       . .  . ..... ..  .. ..... .  . ......  ..   ..... . ",\r
-" . ....  ..   ....... .  . .. ..   ..      .. .  . ...... .  . ...... .  . ...........   .... . ",\r
-" . .... ...   ....... .  . ......  ..  ...... .  . .......    ....... .  . ............   ... . ",\r
-" . .........   ...... .  . ..........  ...... .  . .......    ....... .  . .............   .. . ",\r
-" . .........   ...... .  . ..........  ...... .  . ........  ........ .  . ..............  .. . ",\r
-" . .......... ....... .  . .................. .  . ........  ........ .  . .................. . ",\r
-" . .................. .  . .................. .  . .................. .  . .................. . ",\r
-"                                                                                                ",\r
-"   ..................      ..................      ..................      ..................   ",\r
-"                                                                                                ",\r
-"                                                                                                ",\r
-"   ..................      ..................      ..................      ..................   ",\r
-"                                                                                                ",\r
-" . .................. .  . .................. .  . .................. .  . .................. . ",\r
-" . .................. .  . .................. .  . .................. .  . .................. . ",\r
-" . .................. .  . ........  ........ .  . ..  ..........  .. .  . ..  ........... .. . ",\r
-" . .................. .  . .......    ....... .  . ..   ........   .. .  . ...  .      ..  .. . ",\r
-" . .................. .  . .......    ....... .  . ...   ......   ... .  . ....           ... . ",\r
-" . .......    ....... .  . ......  ..  ...... .  . ....          .... .  . .....   ...   .... . ",\r
-" . ......      ...... .  . ......  ..  ...... .  . .....        ..... .  . ......  ...  ..... . ",\r
-" . .....        ..... .  . .....  ....  ..... .  . .....        ..... .  . ......   .   ..... . ",\r
-" . .....   ..   ..... .  . .....  ....  ..... .  . .....        ..... .  . ......       ..... . ",\r
-" . .....   ..   ..... .  . ....  ......  .... .  . .....        ..... .  . ......       ..... . ",\r
-" . .....        ..... .  . ....  ......  .... .  . .....        ..... .  . ......      ...... . ",\r
-" . ......      ...... .  . ...  ........  ... .  . .....        ..... .  . ......  ...  ..... . ",\r
-" . .......    ....... .  . ...  ........  ... .  . ....          .... .  . .....   ....  .... . ",\r
-" . .................. .  . ..  ..........  .. .  . ...   ......   ... .  . ....    .....  ... . ",\r
-" . .................. .  . ..              .. .  . ..   ........   .. .  . ...  .  ......  .. . ",\r
-" . .................. .  . ...            ... .  . ..  ..........  .. .  . ..  ........... .. . ",\r
-" . .................. .  . .................. .  . .................. .  . .................. . ",\r
-" . .................. .  . .................. .  . .................. .  . .................. . ",\r
-"                                                                                                ",\r
-"   ..................      ..................      ..................      ..................   ",\r
-"                                                                                                "};\r
+/* XPM */
+static const char * toolpal1_xpm[] = {
+"96 48 2 1",
+"      c #000000",
+".     c #FFFFFF",
+"                                                                                                ",
+"   ..................      ..................      ..................      ..................   ",
+"                                                                                                ",
+" . .................. .  . .................. .  . .................. .  . .................. . ",
+" . .... ............. .  . .................. .  . ........  ........ .  . .................. . ",
+" . ....  ............ .  . .................. .  . ........  ........ .  . ......  .......... . ",
+" . ....   ........... .  . .. ............... .  . .......    ....... .  . ....  ..  ........ . ",
+" . ....    .......... .  . ..  .............. .  . .......    ....... .  . ... ...... ....... . ",
+" . ....     ......... .  . ..   ............. .  . ...... .  . ...... .  . ... ...... ....... . ",
+" . ....      ........ .  . ..    ............ .  . ..... ..  .. ..... .  . .. ........ ...... . ",
+" . ....       ....... .  . ..     ...      .. .  . ...  ...  ...  ... .  . .. ........ ...... . ",
+" . ....        ...... .  . ..      ..       . .  . .                . .  . ... ...... ....... . ",
+" . ....         ..... .  . ..       .  ...  . .  . .                . .  . ... ...... ....... . ",
+" . ....      ........ .  . ..     ...  ...  . .  . ...  ...  ...  ... .  . ....  ..    ...... . ",
+" . ....      ........ .  . ..     ...       . .  . ..... ..  .. ..... .  . ......  ..   ..... . ",
+" . ....  ..   ....... .  . .. ..   ..      .. .  . ...... .  . ...... .  . ...........   .... . ",
+" . .... ...   ....... .  . ......  ..  ...... .  . .......    ....... .  . ............   ... . ",
+" . .........   ...... .  . ..........  ...... .  . .......    ....... .  . .............   .. . ",
+" . .........   ...... .  . ..........  ...... .  . ........  ........ .  . ..............  .. . ",
+" . .......... ....... .  . .................. .  . ........  ........ .  . .................. . ",
+" . .................. .  . .................. .  . .................. .  . .................. . ",
+"                                                                                                ",
+"   ..................      ..................      ..................      ..................   ",
+"                                                                                                ",
+"                                                                                                ",
+"   ..................      ..................      ..................      ..................   ",
+"                                                                                                ",
+" . .................. .  . .................. .  . .................. .  . .................. . ",
+" . .................. .  . .................. .  . .................. .  . .................. . ",
+" . .................. .  . ........  ........ .  . ..  ..........  .. .  . ..  ........... .. . ",
+" . .................. .  . .......    ....... .  . ..   ........   .. .  . ...  .      ..  .. . ",
+" . .................. .  . .......    ....... .  . ...   ......   ... .  . ....           ... . ",
+" . .......    ....... .  . ......  ..  ...... .  . ....          .... .  . .....   ...   .... . ",
+" . ......      ...... .  . ......  ..  ...... .  . .....        ..... .  . ......  ...  ..... . ",
+" . .....        ..... .  . .....  ....  ..... .  . .....        ..... .  . ......   .   ..... . ",
+" . .....   ..   ..... .  . .....  ....  ..... .  . .....        ..... .  . ......       ..... . ",
+" . .....   ..   ..... .  . ....  ......  .... .  . .....        ..... .  . ......       ..... . ",
+" . .....        ..... .  . ....  ......  .... .  . .....        ..... .  . ......      ...... . ",
+" . ......      ...... .  . ...  ........  ... .  . .....        ..... .  . ......  ...  ..... . ",
+" . .......    ....... .  . ...  ........  ... .  . ....          .... .  . .....   ....  .... . ",
+" . .................. .  . ..  ..........  .. .  . ...   ......   ... .  . ....    .....  ... . ",
+" . .................. .  . ..              .. .  . ..   ........   .. .  . ...  .  ......  .. . ",
+" . .................. .  . ...            ... .  . ..  ..........  .. .  . ..  ........... .. . ",
+" . .................. .  . .................. .  . .................. .  . .................. . ",
+" . .................. .  . .................. .  . .................. .  . .................. . ",
+"                                                                                                ",
+"   ..................      ..................      ..................      ..................   ",
+"                                                                                                "};
index 84eaf300f51e3a6a73cbbe9a4894a94e7d92032f..5fec44024f271ef2a3f51817a0c702ca9d05d768 100755 (executable)
-//\r
-// CHARNAMES.CPP\r
-//\r
-// A header file that links Unicode character names to character numbers.\r
-// by James L. Hammons\r
-// (C) 2004 Underground Software\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  -------------------------------------------------------------\r
-// JLH  ??/??/200?  Created this file\r
-//\r
-\r
-unsigned char macStdNames[] = {\r
-  "\x06""notdef"\r
-  "\x05"".null"\r
-  "\x02""CR"\r
-  "\x05""space"\r
-  "\x06""exclam"\r
-  "\x08""quotedbl"\r
-  "\x0A""numbersign"\r
-  "\x06""dollar"\r
-  "\x07""percent"\r
-  "\x09""ampersand"\r
-  "\x0B""quotesingle"\r
-  "\x09""parenleft"\r
-  "\x0A""parenright"\r
-  "\x08""asterisk"\r
-  "\x04""plus"\r
-  "\x05""comma"\r
-  "\x06""hyphen"\r
-  "\x06""period"\r
-  "\x05""slash"\r
-  "\x04""zero"\r
-  "\x03""one"\r
-  "\x03""two"\r
-  "\x05""three"\r
-  "\x04""four"\r
-  "\x04""five"\r
-  "\x03""six"\r
-  "\x05""seven"\r
-  "\x05""eight"\r
-  "\x04""nine"\r
-  "\x05""colon"\r
-  "\x09""semicolon"\r
-  "\x04""less"\r
-  "\x05""equal"\r
-  "\x07""greater"\r
-  "\x08""question"\r
-  "\x02""at"\r
-  "\x01""A"\r
-  "\x01""B"\r
-  "\x01""C"\r
-  "\x01""D"\r
-  "\x01""E"\r
-  "\x01""F"\r
-  "\x01""G"\r
-  "\x01""H"\r
-  "\x01""I"\r
-  "\x01""J"\r
-  "\x01""K"\r
-  "\x01""L"\r
-  "\x01""M"\r
-  "\x01""N"\r
-  "\x01""O"\r
-  "\x01""P"\r
-  "\x01""Q"\r
-  "\x01""R"\r
-  "\x01""S"\r
-  "\x01""T"\r
-  "\x01""U"\r
-  "\x01""V"\r
-  "\x01""W"\r
-  "\x01""X"\r
-  "\x01""Y"\r
-  "\x01""Z"\r
-  "\x0B""bracketleft"\r
-  "\x09""backslash"\r
-  "\x0C""bracketright"\r
-  "\x0B""asciicircum"\r
-  "\x0A""underscore"\r
-  "\x05""grave"\r
-  "\x01""a"\r
-  "\x01""b"\r
-  "\x01""c"\r
-  "\x01""d"\r
-  "\x01""e"\r
-  "\x01""f"\r
-  "\x01""g"\r
-  "\x01""h"\r
-  "\x01""i"\r
-  "\x01""j"\r
-  "\x01""k"\r
-  "\x01""l"\r
-  "\x01""m"\r
-  "\x01""n"\r
-  "\x01""o"\r
-  "\x01""p"\r
-  "\x01""q"\r
-  "\x01""r"\r
-  "\x01""s"\r
-  "\x01""t"\r
-  "\x01""u"\r
-  "\x01""v"\r
-  "\x01""w"\r
-  "\x01""x"\r
-  "\x01""y"\r
-  "\x01""z"\r
-  "\x09""braceleft"\r
-  "\x03""bar"\r
-  "\x0A""braceright"\r
-  "\x0A""asciitilde"\r
-  "\x09""Adieresis"\r
-  "\x05""Aring"\r
-  "\x08""Ccedilla"\r
-  "\x06""Eacute"\r
-  "\x06""Ntilde"\r
-  "\x09""Odieresis"\r
-  "\x09""Udieresis"\r
-  "\x06""aacute"\r
-  "\x06""agrave"\r
-  "\x0B""acircumflex"\r
-  "\x09""adieresis"\r
-  "\x06""atilde"\r
-  "\x05""aring"\r
-  "\x08""ccedilla"\r
-  "\x06""eacute"\r
-  "\x06""egrave"\r
-  "\x0B""ecircumflex"\r
-  "\x09""edieresis"\r
-  "\x06""iacute"\r
-  "\x06""igrave"\r
-  "\x0B""icircumflex"\r
-  "\x09""idieresis"\r
-  "\x06""ntilde"\r
-  "\x06""oacute"\r
-  "\x06""ograve"\r
-  "\x0B""ocircumflex"\r
-  "\x09""odieresis"\r
-  "\x06""otilde"\r
-  "\x06""uacute"\r
-  "\x06""ugrave"\r
-  "\x0B""ucircumflex"\r
-  "\x09""udieresis"\r
-  "\x06""dagger"\r
-  "\x06""degree"\r
-  "\x04""cent"\r
-  "\x08""sterling"\r
-  "\x07""section"\r
-  "\x06""bullet"\r
-  "\x09""paragraph"\r
-  "\x0A""germandbls"\r
-  "\x0A""registered"\r
-  "\x09""copyright"\r
-  "\x09""trademark"\r
-  "\x05""acute"\r
-  "\x08""dieresis"\r
-  "\x08""notequal"\r
-  "\x02""AE"\r
-  "\x06""Oslash"\r
-  "\x08""infinity"\r
-  "\x09""plusminus"\r
-  "\x09""lessequal"\r
-  "\x0C""greaterequal"\r
-  "\x03""yen"\r
-  "\x03""mu1"\r
-  "\x0B""partialdiff"\r
-  "\x09""summation"\r
-  "\x07""product"\r
-  "\x02""pi"\r
-  "\x08""integral"\r
-  "\x0B""ordfeminine"\r
-  "\x0C""ordmasculine"\r
-  "\x03""Ohm"\r
-  "\x02""ae"\r
-  "\x06""oslash"\r
-  "\x0C""questiondown"\r
-  "\x0A""exclamdown"\r
-  "\x0A""logicalnot"\r
-  "\x07""radical"\r
-  "\x06""florin"\r
-  "\x0B""approxequal"\r
-  "\x09""increment"\r
-  "\x0D""guillemotleft"\r
-  "\x0E""guillemotright"\r
-  "\x08""ellipsis"\r
-  "\x07""nbspace"\r
-  "\x06""Agrave"\r
-  "\x06""Atilde"\r
-  "\x06""Otilde"\r
-  "\x02""OE"\r
-  "\x02""oe"\r
-  "\x06""endash"\r
-  "\x06""emdash"\r
-  "\x0C""quotedblleft"\r
-  "\x0D""quotedblright"\r
-  "\x09""quoteleft"\r
-  "\x0A""quoteright"\r
-  "\x06""divide"\r
-  "\x07""lozenge"\r
-  "\x09""ydieresis"\r
-  "\x09""Ydieresis"\r
-  "\x08""fraction"\r
-  "\x08""currency"\r
-  "\x0D""guilsinglleft"\r
-  "\x0E""guilsinglright"\r
-  "\x02""fi"\r
-  "\x02""fl"\r
-  "\x09""daggerdbl"\r
-  "\x0E""periodcentered"\r
-  "\x0E""quotesinglbase"\r
-  "\x0C""quotedblbase"\r
-  "\x0B""perthousand"\r
-  "\x0B""Acircumflex"\r
-  "\x0B""Ecircumflex"\r
-  "\x06""Aacute"\r
-  "\x09""Edieresis"\r
-  "\x06""Egrave"\r
-  "\x06""Iacute"\r
-  "\x0B""Icircumflex"\r
-  "\x09""Idieresis"\r
-  "\x06""Igrave"\r
-  "\x06""Oacute"\r
-  "\x0B""Ocircumflex"\r
-  "\x09""applelogo"\r
-  "\x06""Ograve"\r
-  "\x06""Uacute"\r
-  "\x0B""Ucircumflex"\r
-  "\x06""Ugrave"\r
-  "\x08""dotlessi"\r
-  "\x0A""circumflex"\r
-  "\x05""tilde"\r
-  "\x09""overscore"\r
-  "\x05""breve"\r
-  "\x09""dotaccent"\r
-  "\x04""ring"\r
-  "\x07""cedilla"\r
-  "\x0C""hungarumlaut"\r
-  "\x06""ogonek"\r
-  "\x05""caron"\r
-  "\x06""Lslash"\r
-  "\x06""lslash"\r
-  "\x06""Scaron"\r
-  "\x06""scaron"\r
-  "\x06""Zcaron"\r
-  "\x06""zcaron"\r
-  "\x09""brokenbar"\r
-  "\x03""Eth"\r
-  "\x03""eth"\r
-  "\x06""Yacute"\r
-  "\x06""yacute"\r
-  "\x05""Thorn"\r
-  "\x05""thorn"\r
-  "\x05""minus"\r
-  "\x08""multiply"\r
-  "\x0B""onesuperior"\r
-  "\x0B""twosuperior"\r
-  "\x0D""threesuperior"\r
-  "\x07""onehalf"\r
-  "\x0A""onequarter"\r
-  "\x0D""threequarters"\r
-  "\x05""franc"\r
-  "\x06""Gbreve"\r
-  "\x06""gbreve"\r
-  "\x04""Idot"\r
-  "\x08""Scedilla"\r
-  "\x08""scedilla"\r
-  "\x06""Cacute"\r
-  "\x06""cacute"\r
-  "\x06""Ccaron"\r
-  "\x06""ccaron"\r
-  "\x07""dmacron"\r
-};\r
-\r
-/*struct unicodeChar\r
-{\r
-  int cNum;\r
-\r
-};*/\r
-\r
-unsigned char unicodeChars[] = {\r
-  "\x00\x20""space\0"\r
-  "\x00\x21""exclamation mark\0"\r
-  "\x00\x22""quotation mark\0"\r
-  "\x00\x23""number sign\0"\r
-\r
-};\r
-\r
-/*\r
-\r
-0023   NUMBER SIGN\r
-       = pound sign, hash, crosshatch, octothorpe\r
-0024   DOLLAR SIGN\r
-       = milreis, escudo\r
-       * glyph may have one or two vertical bars\r
-       * other currency symbol characters: 20A0-20AF\r
-       x (currency sign - 00A4)\r
-0025   PERCENT SIGN\r
-       x (arabic percent sign - 066A)\r
-       x (per mille sign - 2030)\r
-       x (per ten thousand sign - 2031)\r
-0026   AMPERSAND\r
-0027   APOSTROPHE\r
-       = APOSTROPHE-QUOTE\r
-       = APL quote\r
-       * neutral (vertical) glyph having mixed usage\r
-       * preferred character for apostrophe is 2019\r
-       * preferred characters in English for paired quotation marks are 2018 & 2019\r
-       x (modifier letter prime - 02B9)\r
-       x (modifier letter apostrophe - 02BC)\r
-       x (modifier letter vertical line - 02C8)\r
-       x (combining acute accent - 0301)\r
-       x (prime - 2032)\r
-0028   LEFT PARENTHESIS\r
-       = OPENING PARENTHESIS\r
-0029   RIGHT PARENTHESIS\r
-       = CLOSING PARENTHESIS\r
-       * see discussion on semantics of paired bracketing characters\r
-002A   ASTERISK\r
-       = star (on phone keypads)\r
-       x (arabic five pointed star - 066D)\r
-       x (asterisk operator - 2217)\r
-       x (heavy asterisk - 2731)\r
-002B   PLUS SIGN\r
-002C   COMMA\r
-       = decimal separator\r
-       x (arabic comma - 060C)\r
-       x (single low-9 quotation mark - 201A)\r
-       x (ideographic comma - 3001)\r
-002D   HYPHEN-MINUS\r
-       = hyphen or minus sign\r
-       * used for either hyphen or minus sign\r
-       x (hyphen - 2010)\r
-       x (non-breaking hyphen - 2011)\r
-       x (figure dash - 2012)\r
-       x (en dash - 2013)\r
-       x (minus sign - 2212)\r
-002E   FULL STOP\r
-       = PERIOD\r
-       = dot, decimal point\r
-       * may be rendered as a raised decimal point in old style numbers\r
-       x (arabic full stop - 06D4)\r
-       x (ideographic full stop - 3002)\r
-002F   SOLIDUS\r
-       = SLASH\r
-       = virgule, shilling (British)\r
-       x (latin letter dental click - 01C0)\r
-       x (combining long solidus overlay - 0338)\r
-       x (fraction slash - 2044)\r
-       x (division slash - 2215)\r
-0030   DIGIT ZERO\r
-0031   DIGIT ONE\r
-0032   DIGIT TWO\r
-0033   DIGIT THREE\r
-0034   DIGIT FOUR\r
-0035   DIGIT FIVE\r
-0036   DIGIT SIX\r
-0037   DIGIT SEVEN\r
-0038   DIGIT EIGHT\r
-0039   DIGIT NINE\r
-003A   COLON\r
-       x (armenian full stop - 0589)\r
-       x (hebrew punctuation sof pasuq - 05C3)\r
-       x (ratio - 2236)\r
-003B   SEMICOLON\r
-       x (greek question mark - 037E)\r
-       x (arabic semicolon - 061B)\r
-003C   LESS-THAN SIGN\r
-       x (single left-pointing angle quotation mark - 2039)\r
-       x (left-pointing angle bracket - 2329)\r
-       x (left angle bracket - 3008)\r
-003D   EQUALS SIGN\r
-       * other related characters: 2241-2263\r
-       x (not equal to - 2260)\r
-       x (identical to - 2261)\r
-003E   GREATER-THAN SIGN\r
-       x (single right-pointing angle quotation mark - 203A)\r
-       x (right-pointing angle bracket - 232A)\r
-       x (right angle bracket - 3009)\r
-003F   QUESTION MARK\r
-       x (inverted question mark - 00BF)\r
-       x (greek question mark - 037E)\r
-       x (arabic question mark - 061F)\r
-       x (interrobang - 203D)\r
-       x (question exclamation mark - 2048)\r
-       x (exclamation question mark - 2049)\r
-0040   COMMERCIAL AT\r
-0041   LATIN CAPITAL LETTER A\r
-0042   LATIN CAPITAL LETTER B\r
-       x (script capital b - 212C)\r
-0043   LATIN CAPITAL LETTER C\r
-       x (double-struck capital c - 2102)\r
-       x (black-letter capital c - 212D)\r
-0044   LATIN CAPITAL LETTER D\r
-0045   LATIN CAPITAL LETTER E\r
-       x (euler constant - 2107)\r
-       x (script capital e - 2130)\r
-0046   LATIN CAPITAL LETTER F\r
-       x (script capital f - 2131)\r
-       x (turned capital f - 2132)\r
-0047   LATIN CAPITAL LETTER G\r
-0048   LATIN CAPITAL LETTER H\r
-       x (script capital h - 210B)\r
-       x (black-letter capital h - 210C)\r
-       x (double-struck capital h - 210D)\r
-0049   LATIN CAPITAL LETTER I\r
-       * Turkish and Azerbaijani use 0131 for lowercase\r
-       x (latin capital letter i with dot above - 0130)\r
-       x (cyrillic capital letter byelorussian-ukrainian i - 0406)\r
-       x (cyrillic letter palochka - 04C0)\r
-       x (script capital i - 2110)\r
-       x (black-letter capital i - 2111)\r
-       x (roman numeral one - 2160)\r
-004A   LATIN CAPITAL LETTER J\r
-004B   LATIN CAPITAL LETTER K\r
-       x (kelvin sign - 212A)\r
-004C   LATIN CAPITAL LETTER L\r
-       x (script capital l - 2112)\r
-004D   LATIN CAPITAL LETTER M\r
-       x (script capital m - 2133)\r
-004E   LATIN CAPITAL LETTER N\r
-       x (double-struck capital n - 2115)\r
-004F   LATIN CAPITAL LETTER O\r
-0050   LATIN CAPITAL LETTER P\r
-       x (double-struck capital p - 2119)\r
-0051   LATIN CAPITAL LETTER Q\r
-       x (double-struck capital q - 211A)\r
-0052   LATIN CAPITAL LETTER R\r
-       x (script capital r - 211B)\r
-       x (black-letter capital r - 211C)\r
-       x (double-struck capital r - 211D)\r
-0053   LATIN CAPITAL LETTER S\r
-0054   LATIN CAPITAL LETTER T\r
-0055   LATIN CAPITAL LETTER U\r
-0056   LATIN CAPITAL LETTER V\r
-0057   LATIN CAPITAL LETTER W\r
-0058   LATIN CAPITAL LETTER X\r
-0059   LATIN CAPITAL LETTER Y\r
-005A   LATIN CAPITAL LETTER Z\r
-       x (double-struck capital z - 2124)\r
-       x (black-letter capital z - 2128)\r
-005B   LEFT SQUARE BRACKET\r
-       = OPENING SQUARE BRACKET\r
-       * other bracket characters: 3008-301B\r
-005C   REVERSE SOLIDUS\r
-       = BACKSLASH\r
-       x (set minus - 2216)\r
-005D   RIGHT SQUARE BRACKET\r
-       = CLOSING SQUARE BRACKET\r
-005E   CIRCUMFLEX ACCENT\r
-       * this is a spacing character\r
-       x (modifier letter up arrowhead - 02C4)\r
-       x (modifier letter circumflex accent - 02C6)\r
-       x (combining circumflex accent - 0302)\r
-       x (up arrowhead - 2303)\r
-005F   LOW LINE\r
-       = SPACING UNDERSCORE\r
-       * this is a spacing character\r
-       x (modifier letter low macron - 02CD)\r
-       x (combining macron below - 0331)\r
-       x (combining low line - 0332)\r
-       x (double low line - 2017)\r
-0060   GRAVE ACCENT\r
-       * this is a spacing character\r
-       x (modifier letter grave accent - 02CB)\r
-       x (combining grave accent - 0300)\r
-       x (reversed prime - 2035)\r
-0061   LATIN SMALL LETTER A\r
-0062   LATIN SMALL LETTER B\r
-0063   LATIN SMALL LETTER C\r
-0064   LATIN SMALL LETTER D\r
-0065   LATIN SMALL LETTER E\r
-       x (estimated symbol - 212E)\r
-       x (script small e - 212F)\r
-0066   LATIN SMALL LETTER F\r
-0067   LATIN SMALL LETTER G\r
-       x (latin small letter script g - 0261)\r
-       x (script small g - 210A)\r
-0068   LATIN SMALL LETTER H\r
-       x (cyrillic small letter shha - 04BB)\r
-       x (planck constant - 210E)\r
-0069   LATIN SMALL LETTER I\r
-       * Turkish and Azerbaijani use 0130 for uppercase\r
-       x (latin small letter dotless i - 0131)\r
-006A   LATIN SMALL LETTER J\r
-006B   LATIN SMALL LETTER K\r
-006C   LATIN SMALL LETTER L\r
-       x (script small l - 2113)\r
-006D   LATIN SMALL LETTER M\r
-006E   LATIN SMALL LETTER N\r
-       x (superscript latin small letter n - 207F)\r
-006F   LATIN SMALL LETTER O\r
-       x (script small o - 2134)\r
-0070   LATIN SMALL LETTER P\r
-0071   LATIN SMALL LETTER Q\r
-0072   LATIN SMALL LETTER R\r
-0073   LATIN SMALL LETTER S\r
-0074   LATIN SMALL LETTER T\r
-0075   LATIN SMALL LETTER U\r
-0076   LATIN SMALL LETTER V\r
-0077   LATIN SMALL LETTER W\r
-0078   LATIN SMALL LETTER X\r
-0079   LATIN SMALL LETTER Y\r
-007A   LATIN SMALL LETTER Z\r
-       x (latin small letter z with stroke - 01B6)\r
-007B   LEFT CURLY BRACKET\r
-       = OPENING CURLY BRACKET\r
-       = opening brace\r
-007C   VERTICAL LINE\r
-       = VERTICAL BAR\r
-       * used in pairs to indicate absolute value\r
-       x (latin letter dental click - 01C0)\r
-       x (hebrew punctuation paseq - 05C0)\r
-       x (divides - 2223)\r
-       x (light vertical bar - 2758)\r
-007D   RIGHT CURLY BRACKET\r
-       = CLOSING CURLY BRACKET\r
-       = closing brace\r
-007E   TILDE\r
-       * this is a spacing character\r
-       x (small tilde - 02DC)\r
-       x (combining tilde - 0303)\r
-       x (tilde operator - 223C)\r
-       x (fullwidth tilde - FF5E)\r
-007F   <control>\r
-       = DELETE\r
-@@     0080    C1 Controls and Latin-1 Supplement (Latin-1 Supplement) 00FF\r
-@              C1 controls\r
-@+             Alias names are those for ISO 6429.\r
-0080   <control>\r
-0081   <control>\r
-0082   <control>\r
-       = BREAK PERMITTED HERE\r
-0083   <control>\r
-       = NO BREAK HERE\r
-0084   <control>\r
-0085   <control>\r
-       = NEXT LINE\r
-0086   <control>\r
-       = START OF SELECTED AREA\r
-0087   <control>\r
-       = END OF SELECTED AREA\r
-0088   <control>\r
-       = CHARACTER TABULATION SET\r
-0089   <control>\r
-       = CHARACTER TABULATION WITH JUSTIFICATION\r
-008A   <control>\r
-       = LINE TABULATION SET\r
-008B   <control>\r
-       = PARTIAL LINE DOWN\r
-008C   <control>\r
-       = PARTIAL LINE UP\r
-008D   <control>\r
-       = REVERSE LINE FEED\r
-008E   <control>\r
-       = SINGLE SHIFT TWO\r
-008F   <control>\r
-       = SINGLE SHIFT THREE\r
-0090   <control>\r
-       = DEVICE CONTROL STRING\r
-0091   <control>\r
-       = PRIVATE USE ONE\r
-0092   <control>\r
-       = PRIVATE USE TWO\r
-0093   <control>\r
-       = SET TRANSMIT STATE\r
-0094   <control>\r
-       = CANCEL CHARACTER\r
-0095   <control>\r
-       = MESSAGE WAITING\r
-0096   <control>\r
-       = START OF GUARDED AREA\r
-0097   <control>\r
-       = END OF GUARDED AREA\r
-0098   <control>\r
-       = START OF STRING\r
-0099   <control>\r
-009A   <control>\r
-       = SINGLE CHARACTER INTRODUCER\r
-009B   <control>\r
-       = CONTROL SEQUENCE INTRODUCER\r
-009C   <control>\r
-       = STRING TERMINATOR\r
-009D   <control>\r
-       = OPERATING SYSTEM COMMAND\r
-009E   <control>\r
-       = PRIVACY MESSAGE\r
-009F   <control>\r
-       = APPLICATION PROGRAM COMMAND\r
-@              ISO 8859-1 (aka Latin-1)\r
-00A0   NO-BREAK SPACE\r
-       x (space - 0020)\r
-       x (figure space - 2007)\r
-       x (narrow no-break space - 202F)\r
-       x (zero width no-break space - FEFF)\r
-       # <noBreak> 0020\r
-00A1   INVERTED EXCLAMATION MARK\r
-       * Spanish, Asturian, Galician\r
-       x (exclamation mark - 0021)\r
-00A2   CENT SIGN\r
-00A3   POUND SIGN\r
-       = pound sterling, Irish punt\r
-       x (lira sign - 20A4)\r
-00A4   CURRENCY SIGN\r
-       = Filzlaus, Ricardi-Sonne (German names)\r
-       * other currency symbol characters: 20A0-20AF\r
-       x (dollar sign - 0024)\r
-00A5   YEN SIGN\r
-       = yuan sign\r
-       * glyph may have one or two crossbars\r
-00A6   BROKEN BAR\r
-       = BROKEN VERTICAL BAR\r
-       = parted rule (in typography)\r
-00A7   SECTION SIGN\r
-       * paragraph sign in some European usage\r
-00A8   DIAERESIS\r
-       * this is a spacing character\r
-       x (combining diaeresis - 0308)\r
-       # 0020 0308\r
-00A9   COPYRIGHT SIGN\r
-       x (sound recording copyright - 2117)\r
-00AA   FEMININE ORDINAL INDICATOR\r
-       * Spanish\r
-       # <super> 0061\r
-00AB   LEFT-POINTING DOUBLE ANGLE QUOTATION MARK *\r
-       = LEFT POINTING GUILLEMET\r
-       = chevrons (in typography)\r
-       * usually opening, sometimes closing\r
-       x (much less-than - 226A)\r
-       x (left double angle bracket - 300A)\r
-00AC   NOT SIGN\r
-       = angled dash (in typography)\r
-       x (reversed not sign - 2310)\r
-00AD   SOFT HYPHEN\r
-       = discretionary hyphen\r
-       x (mongolian todo soft hyphen - 1806)\r
-00AE   REGISTERED SIGN\r
-       = REGISTERED TRADE MARK SIGN\r
-00AF   MACRON\r
-       = overline, APL overbar\r
-       * this is a spacing character\r
-       x (modifier letter macron - 02C9)\r
-       x (combining macron - 0304)\r
-       x (combining overline - 0305)\r
-       # 0020 0304\r
-00B0   DEGREE SIGN\r
-       * this is a spacing character\r
-       x (ring above - 02DA)\r
-       x (combining ring above - 030A)\r
-       x (superscript zero - 2070)\r
-       x (ring operator - 2218)\r
-00B1   PLUS-MINUS SIGN\r
-       x (minus-or-plus sign - 2213)\r
-00B2   SUPERSCRIPT TWO\r
-       = squared\r
-       * other superscript digit characters: 2070-2079\r
-       x (superscript one - 00B9)\r
-       # <super> 0032\r
-00B3   SUPERSCRIPT THREE\r
-       = cubed\r
-       x (superscript one - 00B9)\r
-       # <super> 0033\r
-00B4   ACUTE ACCENT\r
-       * this is a spacing character\r
-       x (modifier letter prime - 02B9)\r
-       x (modifier letter acute accent - 02CA)\r
-       x (combining acute accent - 0301)\r
-       x (prime - 2032)\r
-       # 0020 0301\r
-00B5   MICRO SIGN\r
-       # 03BC greek small letter mu\r
-00B6   PILCROW SIGN\r
-       = PARAGRAPH SIGN\r
-       * section sign in some European usage\r
-       x (reversed pilcrow sign - 204B)\r
-       x (curved stem paragraph sign ornament - 2761)\r
-00B7   MIDDLE DOT\r
-       = midpoint (in typography)\r
-       = Georgian comma\r
-       = Greek middle dot\r
-       x (bullet - 2022)\r
-       x (one dot leader - 2024)\r
-       x (hyphenation point - 2027)\r
-       x (bullet operator - 2219)\r
-       x (dot operator - 22C5)\r
-       x (katakana middle dot - 30FB)\r
-00B8   CEDILLA\r
-       * this is a spacing character\r
-       * other spacing accent characters: 02D8-02DB\r
-       x (combining cedilla - 0327)\r
-       # 0020 0327\r
-00B9   SUPERSCRIPT ONE\r
-       x (superscript two - 00B2)\r
-       x (superscript three - 00B3)\r
-       # <super> 0031\r
-00BA   MASCULINE ORDINAL INDICATOR\r
-       * Spanish\r
-       # <super> 006F\r
-00BB   RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK *\r
-       = RIGHT POINTING GUILLEMET\r
-       * usually closing, sometimes opening\r
-       x (much greater-than - 226B)\r
-       x (right double angle bracket - 300B)\r
-00BC   VULGAR FRACTION ONE QUARTER\r
-       * bar may be horizontal or slanted\r
-       * other fraction characters: 2153-215E\r
-       # 0031 2044 0034\r
-00BD   VULGAR FRACTION ONE HALF\r
-       * bar may be horizontal or slanted\r
-       # 0031 2044 0032\r
-00BE   VULGAR FRACTION THREE QUARTERS\r
-       * bar may be horizontal or slanted\r
-       # 0033 2044 0034\r
-00BF   INVERTED QUESTION MARK\r
-       = turned question mark\r
-       * Spanish\r
-       x (question mark - 003F)\r
-00C0   LATIN CAPITAL LETTER A WITH GRAVE\r
-       : 0041 0300\r
-00C1   LATIN CAPITAL LETTER A WITH ACUTE\r
-       : 0041 0301\r
-00C2   LATIN CAPITAL LETTER A WITH CIRCUMFLEX\r
-       : 0041 0302\r
-00C3   LATIN CAPITAL LETTER A WITH TILDE\r
-       : 0041 0303\r
-00C4   LATIN CAPITAL LETTER A WITH DIAERESIS\r
-       : 0041 0308\r
-00C5   LATIN CAPITAL LETTER A WITH RING ABOVE\r
-       x (angstrom sign - 212B)\r
-       : 0041 030A\r
-00C6   LATIN CAPITAL LETTER AE (ash) *\r
-       = LATIN CAPITAL LIGATURE AE\r
-00C7   LATIN CAPITAL LETTER C WITH CEDILLA\r
-       : 0043 0327\r
-00C8   LATIN CAPITAL LETTER E WITH GRAVE\r
-       : 0045 0300\r
-00C9   LATIN CAPITAL LETTER E WITH ACUTE\r
-       : 0045 0301\r
-00CA   LATIN CAPITAL LETTER E WITH CIRCUMFLEX\r
-       : 0045 0302\r
-00CB   LATIN CAPITAL LETTER E WITH DIAERESIS\r
-       : 0045 0308\r
-00CC   LATIN CAPITAL LETTER I WITH GRAVE\r
-       : 0049 0300\r
-00CD   LATIN CAPITAL LETTER I WITH ACUTE\r
-       : 0049 0301\r
-00CE   LATIN CAPITAL LETTER I WITH CIRCUMFLEX\r
-       : 0049 0302\r
-00CF   LATIN CAPITAL LETTER I WITH DIAERESIS\r
-       : 0049 0308\r
-00D0   LATIN CAPITAL LETTER ETH (Icelandic)\r
-       x (latin small letter eth - 00F0)\r
-       x (latin capital letter d with stroke - 0110)\r
-       x (latin capital letter african d - 0189)\r
-00D1   LATIN CAPITAL LETTER N WITH TILDE\r
-       : 004E 0303\r
-00D2   LATIN CAPITAL LETTER O WITH GRAVE\r
-       : 004F 0300\r
-00D3   LATIN CAPITAL LETTER O WITH ACUTE\r
-       : 004F 0301\r
-00D4   LATIN CAPITAL LETTER O WITH CIRCUMFLEX\r
-       : 004F 0302\r
-00D5   LATIN CAPITAL LETTER O WITH TILDE\r
-       : 004F 0303\r
-00D6   LATIN CAPITAL LETTER O WITH DIAERESIS\r
-       : 004F 0308\r
-00D7   MULTIPLICATION SIGN\r
-       = z notation Cartesian product\r
-00D8   LATIN CAPITAL LETTER O WITH STROKE\r
-       = LATIN CAPITAL LETTER O SLASH\r
-       x (empty set - 2205)\r
-00D9   LATIN CAPITAL LETTER U WITH GRAVE\r
-       : 0055 0300\r
-00DA   LATIN CAPITAL LETTER U WITH ACUTE\r
-       : 0055 0301\r
-00DB   LATIN CAPITAL LETTER U WITH CIRCUMFLEX\r
-       : 0055 0302\r
-00DC   LATIN CAPITAL LETTER U WITH DIAERESIS\r
-       : 0055 0308\r
-00DD   LATIN CAPITAL LETTER Y WITH ACUTE\r
-       : 0059 0301\r
-00DE   LATIN CAPITAL LETTER THORN (Icelandic)\r
-00DF   LATIN SMALL LETTER SHARP S (German)\r
-       = Eszett\r
-       * German\r
-       * uppercase is "SS"\r
-       * in origin a ligature of 017F and 0073\r
-       x (greek small letter beta - 03B2)\r
-00E0   LATIN SMALL LETTER A WITH GRAVE\r
-       : 0061 0300\r
-00E1   LATIN SMALL LETTER A WITH ACUTE\r
-       : 0061 0301\r
-00E2   LATIN SMALL LETTER A WITH CIRCUMFLEX\r
-       : 0061 0302\r
-00E3   LATIN SMALL LETTER A WITH TILDE\r
-       * Portuguese\r
-       : 0061 0303\r
-00E4   LATIN SMALL LETTER A WITH DIAERESIS\r
-       : 0061 0308\r
-00E5   LATIN SMALL LETTER A WITH RING ABOVE\r
-       * Danish, Norwegian, Swedish, Walloon\r
-       : 0061 030A\r
-00E6   LATIN SMALL LETTER AE (ash) *\r
-       = LATIN SMALL LIGATURE AE\r
-       = ash (from Old English Ã¦sc)\r
-       * Danish, Norwegian, Icelandic, Faroese, Old English, French, IPA\r
-       x (latin small ligature oe - 0153)\r
-       x (cyrillic small ligature a ie - 04D5)\r
-00E7   LATIN SMALL LETTER C WITH CEDILLA\r
-       : 0063 0327\r
-00E8   LATIN SMALL LETTER E WITH GRAVE\r
-       : 0065 0300\r
-00E9   LATIN SMALL LETTER E WITH ACUTE\r
-       : 0065 0301\r
-00EA   LATIN SMALL LETTER E WITH CIRCUMFLEX\r
-       : 0065 0302\r
-00EB   LATIN SMALL LETTER E WITH DIAERESIS\r
-       : 0065 0308\r
-00EC   LATIN SMALL LETTER I WITH GRAVE\r
-       * Italian, Malagasy\r
-       : 0069 0300\r
-00ED   LATIN SMALL LETTER I WITH ACUTE\r
-       : 0069 0301\r
-00EE   LATIN SMALL LETTER I WITH CIRCUMFLEX\r
-       : 0069 0302\r
-00EF   LATIN SMALL LETTER I WITH DIAERESIS\r
-       : 0069 0308\r
-00F0   LATIN SMALL LETTER ETH (Icelandic)\r
-       * Icelandic, Faroese, Old English, IPA\r
-       x (latin capital letter eth - 00D0)\r
-       x (greek small letter delta - 03B4)\r
-       x (partial differential - 2202)\r
-00F1   LATIN SMALL LETTER N WITH TILDE\r
-       : 006E 0303\r
-00F2   LATIN SMALL LETTER O WITH GRAVE\r
-       : 006F 0300\r
-00F3   LATIN SMALL LETTER O WITH ACUTE\r
-       : 006F 0301\r
-00F4   LATIN SMALL LETTER O WITH CIRCUMFLEX\r
-       : 006F 0302\r
-00F5   LATIN SMALL LETTER O WITH TILDE\r
-       * Portuguese, Estonian\r
-       : 006F 0303\r
-00F6   LATIN SMALL LETTER O WITH DIAERESIS\r
-       : 006F 0308\r
-00F7   DIVISION SIGN\r
-00F8   LATIN SMALL LETTER O WITH STROKE\r
-       = LATIN SMALL LETTER O SLASH\r
-       * Danish, Norwegian, Faroese, IPA\r
-00F9   LATIN SMALL LETTER U WITH GRAVE\r
-       * French, Italian\r
-       : 0075 0300\r
-00FA   LATIN SMALL LETTER U WITH ACUTE\r
-       : 0075 0301\r
-00FB   LATIN SMALL LETTER U WITH CIRCUMFLEX\r
-       : 0075 0302\r
-00FC   LATIN SMALL LETTER U WITH DIAERESIS\r
-       : 0075 0308\r
-00FD   LATIN SMALL LETTER Y WITH ACUTE\r
-       * Czech, Slovak, Icelandic, Faroese, Welsh, Malagasy\r
-       : 0079 0301\r
-00FE   LATIN SMALL LETTER THORN (Icelandic)\r
-       * Icelandic, Old English, phonetics\r
-       * Runic letter borrowed into Latin script\r
-       x (runic letter thurisaz thurs thorn - 16A6)\r
-00FF   LATIN SMALL LETTER Y WITH DIAERESIS\r
-       * French\r
-       x (latin capital letter y with diaeresis - 0178)\r
-       : 0079 0308\r
-@@     0100    Latin Extended-A        017F\r
-@              European Latin\r
-0100   LATIN CAPITAL LETTER A WITH MACRON\r
-       : 0041 0304\r
-0101   LATIN SMALL LETTER A WITH MACRON\r
-       * Latvian, Latin, ...\r
-       : 0061 0304\r
-0102   LATIN CAPITAL LETTER A WITH BREVE\r
-       : 0041 0306\r
-0103   LATIN SMALL LETTER A WITH BREVE\r
-       * Romanian, Vietnamese, Latin, ...\r
-       : 0061 0306\r
-0104   LATIN CAPITAL LETTER A WITH OGONEK\r
-       : 0041 0328\r
-0105   LATIN SMALL LETTER A WITH OGONEK\r
-       * Polish, Lithuanian, ...\r
-       : 0061 0328\r
-0106   LATIN CAPITAL LETTER C WITH ACUTE\r
-       : 0043 0301\r
-0107   LATIN SMALL LETTER C WITH ACUTE\r
-       * Polish, Croatian, ...\r
-       x (cyrillic small letter tshe - 045B)\r
-       : 0063 0301\r
-0108   LATIN CAPITAL LETTER C WITH CIRCUMFLEX\r
-       : 0043 0302\r
-0109   LATIN SMALL LETTER C WITH CIRCUMFLEX\r
-       * Esperanto\r
-       : 0063 0302\r
-010A   LATIN CAPITAL LETTER C WITH DOT ABOVE\r
-       : 0043 0307\r
-010B   LATIN SMALL LETTER C WITH DOT ABOVE\r
-       * Maltese, Irish Gaelic (old orthography)\r
-       : 0063 0307\r
-010C   LATIN CAPITAL LETTER C WITH CARON\r
-       : 0043 030C\r
-010D   LATIN SMALL LETTER C WITH CARON\r
-       * Czech, Slovak, Slovenian, and many other languages\r
-       : 0063 030C\r
-010E   LATIN CAPITAL LETTER D WITH CARON\r
-       * the form using caron/hacek is preferred in all contexts\r
-       : 0044 030C\r
-010F   LATIN SMALL LETTER D WITH CARON\r
-       * Czech, Slovak\r
-       * the form using apostrophe is preferred in typesetting\r
-       : 0064 030C\r
-0110   LATIN CAPITAL LETTER D WITH STROKE\r
-       x (latin capital letter eth - 00D0)\r
-       x (latin small letter d with stroke - 0111)\r
-       x (latin capital letter african d - 0189)\r
-0111   LATIN SMALL LETTER D WITH STROKE\r
-       * Croatian, Vietnamese, Sámi\r
-       x (latin capital letter d with stroke - 0110)\r
-       x (cyrillic small letter dje - 0452)\r
-0112   LATIN CAPITAL LETTER E WITH MACRON\r
-       : 0045 0304\r
-0113   LATIN SMALL LETTER E WITH MACRON\r
-       * Latvian, Latin, ...\r
-       : 0065 0304\r
-0114   LATIN CAPITAL LETTER E WITH BREVE\r
-       : 0045 0306\r
-0115   LATIN SMALL LETTER E WITH BREVE\r
-       * Malay, Latin, ...\r
-       : 0065 0306\r
-0116   LATIN CAPITAL LETTER E WITH DOT ABOVE\r
-       : 0045 0307\r
-0117   LATIN SMALL LETTER E WITH DOT ABOVE\r
-       * Lithuanian\r
-       : 0065 0307\r
-0118   LATIN CAPITAL LETTER E WITH OGONEK\r
-       : 0045 0328\r
-0119   LATIN SMALL LETTER E WITH OGONEK\r
-       * Polish, Lithuanian, ...\r
-       : 0065 0328\r
-011A   LATIN CAPITAL LETTER E WITH CARON\r
-       : 0045 030C\r
-011B   LATIN SMALL LETTER E WITH CARON\r
-       * Czech, ...\r
-       : 0065 030C\r
-011C   LATIN CAPITAL LETTER G WITH CIRCUMFLEX\r
-       : 0047 0302\r
-011D   LATIN SMALL LETTER G WITH CIRCUMFLEX\r
-       * Esperanto\r
-       : 0067 0302\r
-011E   LATIN CAPITAL LETTER G WITH BREVE\r
-       : 0047 0306\r
-011F   LATIN SMALL LETTER G WITH BREVE\r
-       * Turkish, Azerbaijani\r
-       x (latin small letter g with caron - 01E7)\r
-       : 0067 0306\r
-0120   LATIN CAPITAL LETTER G WITH DOT ABOVE\r
-       : 0047 0307\r
-0121   LATIN SMALL LETTER G WITH DOT ABOVE\r
-       * Maltese, Irish Gaelic (old orthography)\r
-       : 0067 0307\r
-0122   LATIN CAPITAL LETTER G WITH CEDILLA\r
-       : 0047 0327\r
-0123   LATIN SMALL LETTER G WITH CEDILLA\r
-       * Latvian\r
-       * there are three major glyph variants\r
-       : 0067 0327\r
-0124   LATIN CAPITAL LETTER H WITH CIRCUMFLEX\r
-       : 0048 0302\r
-0125   LATIN SMALL LETTER H WITH CIRCUMFLEX\r
-       * Esperanto\r
-       : 0068 0302\r
-0126   LATIN CAPITAL LETTER H WITH STROKE\r
-0127   LATIN SMALL LETTER H WITH STROKE\r
-       * Maltese, IPA, ...\r
-       x (cyrillic small letter tshe - 045B)\r
-       x (planck constant over two pi - 210F)\r
-0128   LATIN CAPITAL LETTER I WITH TILDE\r
-       : 0049 0303\r
-0129   LATIN SMALL LETTER I WITH TILDE\r
-       * Greenlandic (old orthography)\r
-       : 0069 0303\r
-012A   LATIN CAPITAL LETTER I WITH MACRON\r
-       : 0049 0304\r
-012B   LATIN SMALL LETTER I WITH MACRON\r
-       * Latvian, Latin, ...\r
-       : 0069 0304\r
-012C   LATIN CAPITAL LETTER I WITH BREVE\r
-       : 0049 0306\r
-012D   LATIN SMALL LETTER I WITH BREVE\r
-       * Latin, ...\r
-       : 0069 0306\r
-012E   LATIN CAPITAL LETTER I WITH OGONEK\r
-       : 0049 0328\r
-012F   LATIN SMALL LETTER I WITH OGONEK\r
-       * Lithuanian, ...\r
-       : 0069 0328\r
-0130   LATIN CAPITAL LETTER I WITH DOT ABOVE\r
-       = LATIN CAPITAL LETTER I DOT\r
-       * Turkish, Azerbaijani\r
-       * lowercase is 0069\r
-       x (latin capital letter i - 0049)\r
-       : 0049 0307\r
-0131   LATIN SMALL LETTER DOTLESS I\r
-       * Turkish, Azerbaijani\r
-       * uppercase is 0049\r
-       x (latin small letter i - 0069)\r
-0132   LATIN CAPITAL LIGATURE IJ\r
-       # 0049 004A\r
-0133   LATIN SMALL LIGATURE IJ\r
-       * Dutch\r
-       # 0069 006A\r
-0134   LATIN CAPITAL LETTER J WITH CIRCUMFLEX\r
-       : 004A 0302\r
-0135   LATIN SMALL LETTER J WITH CIRCUMFLEX\r
-       * Esperanto\r
-       : 006A 0302\r
-0136   LATIN CAPITAL LETTER K WITH CEDILLA\r
-       : 004B 0327\r
-0137   LATIN SMALL LETTER K WITH CEDILLA\r
-       * Latvian\r
-       : 006B 0327\r
-0138   LATIN SMALL LETTER KRA (Greenlandic)\r
-       * Greenlandic (old orthography)\r
-0139   LATIN CAPITAL LETTER L WITH ACUTE\r
-       : 004C 0301\r
-013A   LATIN SMALL LETTER L WITH ACUTE\r
-       * Slovak\r
-       : 006C 0301\r
-013B   LATIN CAPITAL LETTER L WITH CEDILLA\r
-       : 004C 0327\r
-013C   LATIN SMALL LETTER L WITH CEDILLA\r
-       * Latvian\r
-       : 006C 0327\r
-013D   LATIN CAPITAL LETTER L WITH CARON\r
-       : 004C 030C\r
-013E   LATIN SMALL LETTER L WITH CARON\r
-       * Slovak\r
-       * the form using apostrophe is preferred in typesetting\r
-       : 006C 030C\r
-013F   LATIN CAPITAL LETTER L WITH MIDDLE DOT\r
-       * some fonts show the middle dot inside the L, but the preferred form has the dot following the L\r
-       # 004C 00B7\r
-0140   LATIN SMALL LETTER L WITH MIDDLE DOT\r
-       * Catalan\r
-       # 006C 00B7\r
-0141   LATIN CAPITAL LETTER L WITH STROKE\r
-0142   LATIN SMALL LETTER L WITH STROKE\r
-       * Polish, ...\r
-       x (latin small letter l with bar - 019A)\r
-0143   LATIN CAPITAL LETTER N WITH ACUTE\r
-       : 004E 0301\r
-0144   LATIN SMALL LETTER N WITH ACUTE\r
-       * Polish, ...\r
-       : 006E 0301\r
-0145   LATIN CAPITAL LETTER N WITH CEDILLA\r
-       : 004E 0327\r
-0146   LATIN SMALL LETTER N WITH CEDILLA\r
-       * Latvian\r
-       : 006E 0327\r
-0147   LATIN CAPITAL LETTER N WITH CARON\r
-       : 004E 030C\r
-0148   LATIN SMALL LETTER N WITH CARON\r
-       * Czech, Slovak\r
-       : 006E 030C\r
-0149   LATIN SMALL LETTER N PRECEDED BY APOSTROPHE\r
-       = LATIN SMALL LETTER APOSTROPHE N\r
-       * Afrikaans\r
-       * this is not actually a single letter\r
-       # 02BC 006E\r
-014A   LATIN CAPITAL LETTER ENG (Sami)\r
-       * glyph may also have appearance of large form of the small letter\r
-014B   LATIN SMALL LETTER ENG (Sami)\r
-       * Sámi, Mende, IPA, ...\r
-014C   LATIN CAPITAL LETTER O WITH MACRON\r
-       : 004F 0304\r
-014D   LATIN SMALL LETTER O WITH MACRON\r
-       * Latvian, Latin, ...\r
-       : 006F 0304\r
-014E   LATIN CAPITAL LETTER O WITH BREVE\r
-       : 004F 0306\r
-014F   LATIN SMALL LETTER O WITH BREVE\r
-       * Latin\r
-       : 006F 0306\r
-0150   LATIN CAPITAL LETTER O WITH DOUBLE ACUTE\r
-       : 004F 030B\r
-0151   LATIN SMALL LETTER O WITH DOUBLE ACUTE\r
-       * Hungarian\r
-       : 006F 030B\r
-0152   LATIN CAPITAL LIGATURE OE\r
-0153   LATIN SMALL LIGATURE OE\r
-       = LATIN SMALL LETTER O E\r
-       = ethel (from Old English eðel)\r
-       * French, IPA, Old Icelandic, Old English, ...\r
-       x (latin small letter ae - 00E6)\r
-       x (latin letter small capital oe - 0276)\r
-0154   LATIN CAPITAL LETTER R WITH ACUTE\r
-       : 0052 0301\r
-0155   LATIN SMALL LETTER R WITH ACUTE\r
-       * Slovak, ...\r
-       : 0072 0301\r
-0156   LATIN CAPITAL LETTER R WITH CEDILLA\r
-       : 0052 0327\r
-0157   LATIN SMALL LETTER R WITH CEDILLA\r
-       * Latvian\r
-       : 0072 0327\r
-0158   LATIN CAPITAL LETTER R WITH CARON\r
-       : 0052 030C\r
-0159   LATIN SMALL LETTER R WITH CARON\r
-       * Czech, ...\r
-       : 0072 030C\r
-015A   LATIN CAPITAL LETTER S WITH ACUTE\r
-       : 0053 0301\r
-015B   LATIN SMALL LETTER S WITH ACUTE\r
-       * Polish, Indic transliteration, ...\r
-       : 0073 0301\r
-015C   LATIN CAPITAL LETTER S WITH CIRCUMFLEX\r
-       : 0053 0302\r
-015D   LATIN SMALL LETTER S WITH CIRCUMFLEX\r
-       * Esperanto\r
-       : 0073 0302\r
-015E   LATIN CAPITAL LETTER S WITH CEDILLA *\r
-       : 0053 0327\r
-015F   LATIN SMALL LETTER S WITH CEDILLA *\r
-       * Turkish, Azerbaijani, Romanian, ...\r
-       * this character is used in both Turkish and Romanian data\r
-       * a glyph variant with comma below is preferred for Romanian\r
-       x (latin small letter s with comma below - 0219)\r
-       : 0073 0327\r
-0160   LATIN CAPITAL LETTER S WITH CARON\r
-       : 0053 030C\r
-0161   LATIN SMALL LETTER S WITH CARON\r
-       * Czech, Estonian, Finnish, Slovak, and many other languages\r
-       : 0073 030C\r
-0162   LATIN CAPITAL LETTER T WITH CEDILLA *\r
-       : 0054 0327\r
-0163   LATIN SMALL LETTER T WITH CEDILLA *\r
-       * Romanian, Semitic transliteration, ...\r
-       * this character is used in Romanian data\r
-       * a glyph variant with comma below is preferred for Romanian\r
-       x (latin small letter t with comma below - 021B)\r
-       : 0074 0327\r
-0164   LATIN CAPITAL LETTER T WITH CARON\r
-       * the form using caron/hacek is preferred in all contexts\r
-       : 0054 030C\r
-0165   LATIN SMALL LETTER T WITH CARON\r
-       * Czech, Slovak\r
-       * the form using apostrophe is preferred in typesetting\r
-       : 0074 030C\r
-0166   LATIN CAPITAL LETTER T WITH STROKE\r
-0167   LATIN SMALL LETTER T WITH STROKE\r
-       * Sámi\r
-0168   LATIN CAPITAL LETTER U WITH TILDE\r
-       : 0055 0303\r
-0169   LATIN SMALL LETTER U WITH TILDE\r
-       * Greenlandic (old orthography)\r
-       : 0075 0303\r
-016A   LATIN CAPITAL LETTER U WITH MACRON\r
-       : 0055 0304\r
-016B   LATIN SMALL LETTER U WITH MACRON\r
-       * Latvian, Lithuanian, Latin, ...\r
-       : 0075 0304\r
-016C   LATIN CAPITAL LETTER U WITH BREVE\r
-       : 0055 0306\r
-016D   LATIN SMALL LETTER U WITH BREVE\r
-       * Latin, Esperanto, ...\r
-       : 0075 0306\r
-016E   LATIN CAPITAL LETTER U WITH RING ABOVE\r
-       : 0055 030A\r
-016F   LATIN SMALL LETTER U WITH RING ABOVE\r
-       * Czech, ...\r
-       : 0075 030A\r
-0170   LATIN CAPITAL LETTER U WITH DOUBLE ACUTE\r
-       : 0055 030B\r
-0171   LATIN SMALL LETTER U WITH DOUBLE ACUTE\r
-       * Hungarian\r
-       : 0075 030B\r
-0172   LATIN CAPITAL LETTER U WITH OGONEK\r
-       : 0055 0328\r
-0173   LATIN SMALL LETTER U WITH OGONEK\r
-       * Lithuanian\r
-       : 0075 0328\r
-0174   LATIN CAPITAL LETTER W WITH CIRCUMFLEX\r
-       : 0057 0302\r
-0175   LATIN SMALL LETTER W WITH CIRCUMFLEX\r
-       * Welsh\r
-       : 0077 0302\r
-0176   LATIN CAPITAL LETTER Y WITH CIRCUMFLEX\r
-       : 0059 0302\r
-0177   LATIN SMALL LETTER Y WITH CIRCUMFLEX\r
-       * Welsh\r
-       : 0079 0302\r
-0178   LATIN CAPITAL LETTER Y WITH DIAERESIS\r
-       * French, Igbo\r
-       x (latin small letter y with diaeresis - 00FF)\r
-       : 0059 0308\r
-0179   LATIN CAPITAL LETTER Z WITH ACUTE\r
-       : 005A 0301\r
-017A   LATIN SMALL LETTER Z WITH ACUTE\r
-       * Polish, ...\r
-       : 007A 0301\r
-017B   LATIN CAPITAL LETTER Z WITH DOT ABOVE\r
-       : 005A 0307\r
-017C   LATIN SMALL LETTER Z WITH DOT ABOVE\r
-       * Polish, ...\r
-       : 007A 0307\r
-017D   LATIN CAPITAL LETTER Z WITH CARON\r
-       : 005A 030C\r
-017E   LATIN SMALL LETTER Z WITH CARON\r
-       * Czech, Estonian, Finnish, Slovak, Slovenian, and many other languages\r
-       : 007A 030C\r
-017F   LATIN SMALL LETTER LONG S\r
-       * in common use in Roman types until the 18th century\r
-       * in current use in Fraktur and Gaelic types\r
-       # 0073 latin small letter s\r
-@@     0180    Latin Extended-B        024F\r
-@              Latin extended-B\r
-0180   LATIN SMALL LETTER B WITH STROKE\r
-       * Americanist and Indo-Europeanist usage for phonetic beta\r
-       * Old Saxon\r
-       x (greek small letter beta - 03B2)\r
-       x (blank symbol - 2422)\r
-0181   LATIN CAPITAL LETTER B WITH HOOK\r
-       * Zulu, Pan-Nigerian alphabet\r
-       x (latin small letter b with hook - 0253)\r
-0182   LATIN CAPITAL LETTER B WITH TOPBAR\r
-0183   LATIN SMALL LETTER B WITH TOPBAR\r
-       * Zhuang\r
-       * former Soviet minority language scripts\r
-       x (cyrillic capital letter be - 0411)\r
-0184   LATIN CAPITAL LETTER TONE SIX\r
-0185   LATIN SMALL LETTER TONE SIX\r
-       * Zhuang\r
-       * Zhuang tone three is Cyrillic ze\r
-       * Zhuang tone four is Cyrillic che\r
-       x (latin small letter tone two - 01A8)\r
-       x (latin small letter tone five - 01BD)\r
-       x (cyrillic small letter ze - 0437)\r
-       x (cyrillic small letter che - 0447)\r
-       x (cyrillic small letter soft sign - 044C)\r
-0186   LATIN CAPITAL LETTER OPEN O\r
-       * typographically a turned C\r
-       x (latin small letter open o - 0254)\r
-0187   LATIN CAPITAL LETTER C WITH HOOK\r
-0188   LATIN SMALL LETTER C WITH HOOK\r
-       * African\r
-0189   LATIN CAPITAL LETTER AFRICAN D *\r
-       * Ewe\r
-       x (latin capital letter eth - 00D0)\r
-       x (latin capital letter d with stroke - 0110)\r
-       x (latin small letter d with tail - 0256)\r
-018A   LATIN CAPITAL LETTER D WITH HOOK\r
-       * Pan-Nigerian alphabet\r
-       x (latin small letter d with hook - 0257)\r
-018B   LATIN CAPITAL LETTER D WITH TOPBAR\r
-018C   LATIN SMALL LETTER D WITH TOPBAR\r
-       * former-Soviet minority language scripts\r
-018D   LATIN SMALL LETTER TURNED DELTA\r
-       * archaic phonetic for labialized dental fricative\r
-       * recommended spellings 007A 02B7 or 007A 032B\r
-018E   LATIN CAPITAL LETTER REVERSED E\r
-       = LATIN CAPITAL LETTER TURNED E\r
-       * Pan-Nigerian alphabet\r
-       * lowercase is 01DD\r
-018F   LATIN CAPITAL LETTER SCHWA\r
-       * Azerbaijani, ...\r
-       x (latin small letter schwa - 0259)\r
-       x (cyrillic capital letter schwa - 04D8)\r
-0190   LATIN CAPITAL LETTER OPEN E\r
-       = LATIN CAPITAL LETTER EPSILON\r
-       * African\r
-       x (latin small letter open e - 025B)\r
-       x (euler constant - 2107)\r
-0191   LATIN CAPITAL LETTER F WITH HOOK\r
-       * African\r
-0192   LATIN SMALL LETTER F WITH HOOK\r
-       = LATIN SMALL LETTER SCRIPT F\r
-       = Florin currency symbol (Netherlands)\r
-       = function symbol\r
-       = abbreviation convention for folder\r
-0193   LATIN CAPITAL LETTER G WITH HOOK\r
-       * African\r
-       x (latin small letter g with hook - 0260)\r
-0194   LATIN CAPITAL LETTER GAMMA\r
-       * African\r
-       x (latin small letter gamma - 0263)\r
-0195   LATIN SMALL LETTER HV (hwair)\r
-       * Gothic transliteration\r
-       * uppercase is 01F6\r
-0196   LATIN CAPITAL LETTER IOTA\r
-       * African\r
-       x (latin small letter iota - 0269)\r
-0197   LATIN CAPITAL LETTER I WITH STROKE\r
-       = barred i, i bar\r
-       * African\r
-       * ISO 6438 gives lowercase as 026A, not 0268\r
-       x (latin letter small capital i - 026A)\r
-0198   LATIN CAPITAL LETTER K WITH HOOK\r
-0199   LATIN SMALL LETTER K WITH HOOK\r
-       * Hausa, Pan-Nigerian alphabet\r
-019A   LATIN SMALL LETTER L WITH BAR\r
-       = barred l\r
-       * Americanist phonetic usage for 026C\r
-       x (latin small letter l with stroke - 0142)\r
-019B   LATIN SMALL LETTER LAMBDA WITH STROKE\r
-       = barred lambda, lambda bar\r
-       * Americanist phonetic usage\r
-019C   LATIN CAPITAL LETTER TURNED M\r
-       * Zhuang\r
-       x (latin small letter turned m - 026F)\r
-019D   LATIN CAPITAL LETTER N WITH LEFT HOOK\r
-       * African\r
-       x (latin small letter n with left hook - 0272)\r
-019E   LATIN SMALL LETTER N WITH LONG RIGHT LEG\r
-       * archaic phonetic for Japanese syllabic "n"\r
-       * recommended spelling 006E 0329\r
-019F   LATIN CAPITAL LETTER O WITH MIDDLE TILDE *\r
-       = barred o, o bar\r
-       * lowercase is 0275\r
-       * African\r
-       x (cyrillic capital letter barred o - 04E8)\r
-01A0   LATIN CAPITAL LETTER O WITH HORN\r
-       : 004F 031B\r
-01A1   LATIN SMALL LETTER O WITH HORN\r
-       * Vietnamese\r
-       : 006F 031B\r
-01A2   LATIN CAPITAL LETTER OI (gha)\r
-01A3   LATIN SMALL LETTER OI (gha)\r
-       = gha\r
-       * Pan-Turkic Latin alphabets\r
-01A4   LATIN CAPITAL LETTER P WITH HOOK\r
-01A5   LATIN SMALL LETTER P WITH HOOK\r
-       * African\r
-01A6   LATIN LETTER YR *\r
-       * old Norse\r
-       * from German Standard DIN 31624 and ISO 5246-2\r
-       * lowercase is 0280\r
-01A7   LATIN CAPITAL LETTER TONE TWO\r
-01A8   LATIN SMALL LETTER TONE TWO\r
-       * Zhuang\r
-       * typographically a reversed S\r
-       x (latin small letter tone six - 0185)\r
-01A9   LATIN CAPITAL LETTER ESH\r
-       * African\r
-       x (latin small letter esh - 0283)\r
-       x (greek capital letter sigma - 03A3)\r
-01AA   LATIN LETTER REVERSED ESH LOOP\r
-       * archaic phonetic for labialized palatoalveolar or palatal fricative\r
-       * Twi\r
-       * recommended spellings 0283 02B7, 00E7 02B7, 0068 0265, etc.\r
-01AB   LATIN SMALL LETTER T WITH PALATAL HOOK\r
-       * archaic phonetic for palatalized alveolar or dental stop\r
-       * recommended spelling 0074 02B2\r
-01AC   LATIN CAPITAL LETTER T WITH HOOK\r
-01AD   LATIN SMALL LETTER T WITH HOOK\r
-       * African\r
-01AE   LATIN CAPITAL LETTER T WITH RETROFLEX HOOK\r
-       * African\r
-       x (latin small letter t with retroflex hook - 0288)\r
-01AF   LATIN CAPITAL LETTER U WITH HORN\r
-       : 0055 031B\r
-01B0   LATIN SMALL LETTER U WITH HORN\r
-       * Vietnamese\r
-       : 0075 031B\r
-01B1   LATIN CAPITAL LETTER UPSILON\r
-       * African\r
-       * typographically based on turned capital Greek omega\r
-       x (latin small letter upsilon - 028A)\r
-       x (inverted ohm sign - 2127)\r
-01B2   LATIN CAPITAL LETTER V WITH HOOK\r
-       = LATIN CAPITAL LETTER SCRIPT V\r
-       * African\r
-       x (latin small letter v with hook - 028B)\r
-01B3   LATIN CAPITAL LETTER Y WITH HOOK\r
-01B4   LATIN SMALL LETTER Y WITH HOOK\r
-       * Bini, Esoko, and other Edo languages in West Africa\r
-01B5   LATIN CAPITAL LETTER Z WITH STROKE\r
-01B6   LATIN SMALL LETTER Z WITH STROKE\r
-       = barred z, z bar\r
-       * Pan-Turkic Latin orthography\r
-       * handwritten variant of Latin "z"\r
-       x (latin small letter z - 007A)\r
-01B7   LATIN CAPITAL LETTER EZH\r
-       * African, Skolt Sámi\r
-       * lowercase is 0292\r
-       x (latin capital letter yogh - 021C)\r
-       x (cyrillic capital letter abkhasian dze - 04E0)\r
-01B8   LATIN CAPITAL LETTER EZH REVERSED\r
-01B9   LATIN SMALL LETTER EZH REVERSED\r
-       * archaic phonetic for voiced pharyngeal fricative\r
-       * sometimes typographically rendered with a turned digit 3\r
-       * recommended spelling 0295\r
-       x (latin letter pharyngeal voiced fricative - 0295)\r
-       x (arabic letter ain - 0639)\r
-01BA   LATIN SMALL LETTER EZH WITH TAIL\r
-       * archaic phonetic for labialized voiced palatoalveolar or palatal fricative\r
-       * Twi\r
-       * recommended spellings 0292 02B7 or 006A 02B7\r
-01BB   LATIN LETTER TWO WITH STROKE\r
-       * archaic phonetic for [dz] affricate\r
-       * recommended spellings 0292 or 0064 007A\r
-01BC   LATIN CAPITAL LETTER TONE FIVE\r
-01BD   LATIN SMALL LETTER TONE FIVE\r
-       * Zhuang\r
-       x (latin small letter tone six - 0185)\r
-01BE   LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE\r
-       * archaic phonetic for [ts] affricate\r
-       * recommended spelling 0074 0073\r
-       * letter form is actually derived from ligation of ts, rather than inverted glottal stop\r
-01BF   LATIN LETTER WYNN\r
-       = wen\r
-       * Runic letter borrowed into Latin script\r
-       * replaced by "w" in modern transcriptions of Old English\r
-       * uppercase is 01F7\r
-       x (runic letter wunjo wynn w - 16B9)\r
-01C0   LATIN LETTER DENTAL CLICK\r
-       = pipe\r
-       * Khoisan tradition\r
-       * "c" in Zulu orthography\r
-       x (solidus - 002F)\r
-       x (vertical line - 007C)\r
-       x (latin small letter turned t - 0287)\r
-       x (divides - 2223)\r
-01C1   LATIN LETTER LATERAL CLICK\r
-       = double pipe\r
-       * Khoisan tradition\r
-       * "x" in Zulu orthography\r
-       x (latin letter inverted glottal stop - 0296)\r
-       x (parallel to - 2225)\r
-01C2   LATIN LETTER ALVEOLAR CLICK\r
-       = double-barred pipe\r
-       * Khoisan tradition\r
-       x (not equal to - 2260)\r
-01C3   LATIN LETTER RETROFLEX CLICK\r
-       = LATIN LETTER EXCLAMATION MARK\r
-       * Khoisan tradition\r
-       * "q" in Zulu orthography\r
-       x (exclamation mark - 0021)\r
-       x (latin letter stretched c - 0297)\r
-@              Croatian digraphs matching Serbian Cyrillic letters\r
-01C4   LATIN CAPITAL LETTER DZ WITH CARON\r
-       # 0044 017D\r
-01C5   LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON\r
-       # 0044 017E\r
-01C6   LATIN SMALL LETTER DZ WITH CARON\r
-       x (cyrillic small letter dzhe - 045F)\r
-       # 0064 017E\r
-01C7   LATIN CAPITAL LETTER LJ\r
-       # 004C 004A\r
-01C8   LATIN CAPITAL LETTER L WITH SMALL LETTER J\r
-       # 004C 006A\r
-01C9   LATIN SMALL LETTER LJ\r
-       x (cyrillic small letter lje - 0459)\r
-       # 006C 006A\r
-01CA   LATIN CAPITAL LETTER NJ\r
-       # 004E 004A\r
-01CB   LATIN CAPITAL LETTER N WITH SMALL LETTER J\r
-       # 004E 006A\r
-01CC   LATIN SMALL LETTER NJ\r
-       x (cyrillic small letter nje - 045A)\r
-       # 006E 006A\r
-@              Pinyin diacritic-vowel combinations\r
-01CD   LATIN CAPITAL LETTER A WITH CARON\r
-       : 0041 030C\r
-01CE   LATIN SMALL LETTER A WITH CARON\r
-       * Pinyin third tone\r
-       : 0061 030C\r
-01CF   LATIN CAPITAL LETTER I WITH CARON\r
-       : 0049 030C\r
-01D0   LATIN SMALL LETTER I WITH CARON\r
-       * Pinyin third tone\r
-       : 0069 030C\r
-01D1   LATIN CAPITAL LETTER O WITH CARON\r
-       : 004F 030C\r
-01D2   LATIN SMALL LETTER O WITH CARON\r
-       * Pinyin third tone\r
-       : 006F 030C\r
-01D3   LATIN CAPITAL LETTER U WITH CARON\r
-       : 0055 030C\r
-01D4   LATIN SMALL LETTER U WITH CARON\r
-       * Pinyin third tone\r
-       : 0075 030C\r
-01D5   LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON\r
-       : 00DC 0304\r
-01D6   LATIN SMALL LETTER U WITH DIAERESIS AND MACRON\r
-       * Pinyin first tone\r
-       : 00FC 0304\r
-01D7   LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE\r
-       : 00DC 0301\r
-01D8   LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE\r
-       * Pinyin second tone\r
-       : 00FC 0301\r
-01D9   LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON\r
-       : 00DC 030C\r
-01DA   LATIN SMALL LETTER U WITH DIAERESIS AND CARON\r
-       * Pinyin third tone\r
-       : 00FC 030C\r
-01DB   LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE\r
-       : 00DC 0300\r
-01DC   LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE\r
-       * Pinyin fourth tone\r
-       : 00FC 0300\r
-@              Additions\r
-01DD   LATIN SMALL LETTER TURNED E\r
-       * Pan-Nigerian alphabet\r
-       * all other usages of schwa are 0259\r
-       * uppercase is 018E\r
-       x (latin small letter schwa - 0259)\r
-01DE   LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON\r
-       : 00C4 0304\r
-01DF   LATIN SMALL LETTER A WITH DIAERESIS AND MACRON\r
-       * Livonian, Uralicist usage\r
-       : 00E4 0304\r
-01E0   LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON\r
-       : 0226 0304\r
-01E1   LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON\r
-       * Uralicist usage\r
-       : 0227 0304\r
-01E2   LATIN CAPITAL LETTER AE WITH MACRON (ash) *\r
-       : 00C6 0304\r
-01E3   LATIN SMALL LETTER AE WITH MACRON (ash) *\r
-       * Old Norse, Old English\r
-       : 00E6 0304\r
-01E4   LATIN CAPITAL LETTER G WITH STROKE\r
-01E5   LATIN SMALL LETTER G WITH STROKE\r
-       * Skolt Sámi\r
-01E6   LATIN CAPITAL LETTER G WITH CARON\r
-       : 0047 030C\r
-01E7   LATIN SMALL LETTER G WITH CARON\r
-       * Skolt Sámi\r
-       x (latin small letter g with breve - 011F)\r
-       : 0067 030C\r
-01E8   LATIN CAPITAL LETTER K WITH CARON\r
-       : 004B 030C\r
-01E9   LATIN SMALL LETTER K WITH CARON\r
-       * Skolt Sámi\r
-       : 006B 030C\r
-01EA   LATIN CAPITAL LETTER O WITH OGONEK\r
-       : 004F 0328\r
-01EB   LATIN SMALL LETTER O WITH OGONEK\r
-       * Sámi, Iroquoian, Old Icelandic\r
-       : 006F 0328\r
-01EC   LATIN CAPITAL LETTER O WITH OGONEK AND MACRON\r
-       : 01EA 0304\r
-01ED   LATIN SMALL LETTER O WITH OGONEK AND MACRON\r
-       * Old Icelandic\r
-       : 01EB 0304\r
-01EE   LATIN CAPITAL LETTER EZH WITH CARON\r
-       : 01B7 030C\r
-01EF   LATIN SMALL LETTER EZH WITH CARON\r
-       * Skolt Sámi\r
-       : 0292 030C\r
-01F0   LATIN SMALL LETTER J WITH CARON\r
-       * IPA and many languages\r
-       : 006A 030C\r
-01F1   LATIN CAPITAL LETTER DZ\r
-       # 0044 005A\r
-01F2   LATIN CAPITAL LETTER D WITH SMALL LETTER Z\r
-       # 0044 007A\r
-01F3   LATIN SMALL LETTER DZ\r
-       # 0064 007A\r
-01F4   LATIN CAPITAL LETTER G WITH ACUTE\r
-       : 0047 0301\r
-01F5   LATIN SMALL LETTER G WITH ACUTE\r
-       * Macedonian and Serbian transliteration\r
-       : 0067 0301\r
-01F6   LATIN CAPITAL LETTER HWAIR\r
-       * lowercase is 0195\r
-01F7   LATIN CAPITAL LETTER WYNN\r
-       = wen\r
-       * lowercase is 01BF\r
-01F8   LATIN CAPITAL LETTER N WITH GRAVE\r
-       : 004E 0300\r
-01F9   LATIN SMALL LETTER N WITH GRAVE\r
-       * Pinyin\r
-       : 006E 0300\r
-01FA   LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE\r
-       : 00C5 0301\r
-01FB   LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE\r
-       : 00E5 0301\r
-01FC   LATIN CAPITAL LETTER AE WITH ACUTE (ash) *\r
-       : 00C6 0301\r
-01FD   LATIN SMALL LETTER AE WITH ACUTE (ash) *\r
-       : 00E6 0301\r
-01FE   LATIN CAPITAL LETTER O WITH STROKE AND ACUTE\r
-       : 00D8 0301\r
-01FF   LATIN SMALL LETTER O WITH STROKE AND ACUTE\r
-       : 00F8 0301\r
-@              Additions for Slovenian and Croatian\r
-0200   LATIN CAPITAL LETTER A WITH DOUBLE GRAVE\r
-       : 0041 030F\r
-0201   LATIN SMALL LETTER A WITH DOUBLE GRAVE\r
-       : 0061 030F\r
-0202   LATIN CAPITAL LETTER A WITH INVERTED BREVE\r
-       : 0041 0311\r
-0203   LATIN SMALL LETTER A WITH INVERTED BREVE\r
-       : 0061 0311\r
-0204   LATIN CAPITAL LETTER E WITH DOUBLE GRAVE\r
-       : 0045 030F\r
-0205   LATIN SMALL LETTER E WITH DOUBLE GRAVE\r
-       : 0065 030F\r
-0206   LATIN CAPITAL LETTER E WITH INVERTED BREVE\r
-       : 0045 0311\r
-0207   LATIN SMALL LETTER E WITH INVERTED BREVE\r
-       : 0065 0311\r
-0208   LATIN CAPITAL LETTER I WITH DOUBLE GRAVE\r
-       : 0049 030F\r
-0209   LATIN SMALL LETTER I WITH DOUBLE GRAVE\r
-       : 0069 030F\r
-020A   LATIN CAPITAL LETTER I WITH INVERTED BREVE\r
-       : 0049 0311\r
-020B   LATIN SMALL LETTER I WITH INVERTED BREVE\r
-       : 0069 0311\r
-020C   LATIN CAPITAL LETTER O WITH DOUBLE GRAVE\r
-       : 004F 030F\r
-020D   LATIN SMALL LETTER O WITH DOUBLE GRAVE\r
-       : 006F 030F\r
-020E   LATIN CAPITAL LETTER O WITH INVERTED BREVE\r
-       : 004F 0311\r
-020F   LATIN SMALL LETTER O WITH INVERTED BREVE\r
-       : 006F 0311\r
-0210   LATIN CAPITAL LETTER R WITH DOUBLE GRAVE\r
-       : 0052 030F\r
-0211   LATIN SMALL LETTER R WITH DOUBLE GRAVE\r
-       : 0072 030F\r
-0212   LATIN CAPITAL LETTER R WITH INVERTED BREVE\r
-       : 0052 0311\r
-0213   LATIN SMALL LETTER R WITH INVERTED BREVE\r
-       : 0072 0311\r
-0214   LATIN CAPITAL LETTER U WITH DOUBLE GRAVE\r
-       : 0055 030F\r
-0215   LATIN SMALL LETTER U WITH DOUBLE GRAVE\r
-       : 0075 030F\r
-0216   LATIN CAPITAL LETTER U WITH INVERTED BREVE\r
-       : 0055 0311\r
-0217   LATIN SMALL LETTER U WITH INVERTED BREVE\r
-       : 0075 0311\r
-@              Additions for Romanian\r
-0218   LATIN CAPITAL LETTER S WITH COMMA BELOW *\r
-       : 0053 0326\r
-0219   LATIN SMALL LETTER S WITH COMMA BELOW *\r
-       * Romanian, when distinct comma below form is required\r
-       x (latin small letter s with cedilla - 015F)\r
-       : 0073 0326\r
-021A   LATIN CAPITAL LETTER T WITH COMMA BELOW *\r
-       : 0054 0326\r
-021B   LATIN SMALL LETTER T WITH COMMA BELOW *\r
-       * Romanian, when distinct comma below form is required\r
-       x (latin small letter t with cedilla - 0163)\r
-       : 0074 0326\r
-@              Miscellaneous additions\r
-021C   LATIN CAPITAL LETTER YOGH\r
-       x (latin capital letter ezh - 01B7)\r
-021D   LATIN SMALL LETTER YOGH\r
-       * Middle English, Scots\r
-       x (latin small letter ezh - 0292)\r
-       x (ounce sign - 2125)\r
-021E   LATIN CAPITAL LETTER H WITH CARON\r
-       : 0048 030C\r
-021F   LATIN SMALL LETTER H WITH CARON\r
-       * Finnish Romany\r
-       : 0068 030C\r
-0222   LATIN CAPITAL LETTER OU\r
-0223   LATIN SMALL LETTER OU\r
-       * Algonquin, Huron\r
-       x (digit eight - 0038)\r
-0224   LATIN CAPITAL LETTER Z WITH HOOK\r
-0225   LATIN SMALL LETTER Z WITH HOOK\r
-       * Middle High German\r
-0226   LATIN CAPITAL LETTER A WITH DOT ABOVE\r
-       : 0041 0307\r
-0227   LATIN SMALL LETTER A WITH DOT ABOVE\r
-       * Uralicist usage\r
-       : 0061 0307\r
-0228   LATIN CAPITAL LETTER E WITH CEDILLA\r
-       : 0045 0327\r
-0229   LATIN SMALL LETTER E WITH CEDILLA\r
-       : 0065 0327\r
-@              Additions for Livonian\r
-022A   LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON\r
-       : 00D6 0304\r
-022B   LATIN SMALL LETTER O WITH DIAERESIS AND MACRON\r
-       * Livonian\r
-       : 00F6 0304\r
-022C   LATIN CAPITAL LETTER O WITH TILDE AND MACRON\r
-       : 00D5 0304\r
-022D   LATIN SMALL LETTER O WITH TILDE AND MACRON\r
-       * Livonian\r
-       : 00F5 0304\r
-022E   LATIN CAPITAL LETTER O WITH DOT ABOVE\r
-       : 004F 0307\r
-022F   LATIN SMALL LETTER O WITH DOT ABOVE\r
-       * Livonian\r
-       : 006F 0307\r
-0230   LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON\r
-       : 022E 0304\r
-0231   LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON\r
-       * Livonian\r
-       : 022F 0304\r
-0232   LATIN CAPITAL LETTER Y WITH MACRON\r
-       : 0059 0304\r
-0233   LATIN SMALL LETTER Y WITH MACRON\r
-       * Livonian, Cornish\r
-       : 0079 0304\r
-@@     0250    IPA Extensions  02AF\r
-@              IPA extensions\r
-@+             IPA includes basic Latin letters and a number of Latin letters from other blocks.\r
-               x (latin small letter ae - 00E6)\r
-               x (latin small letter c with cedilla - 00E7)\r
-               x (latin small letter eth - 00F0)\r
-               x (latin small letter o with stroke - 00F8)\r
-               x (latin small letter h with stroke - 0127)\r
-               x (latin small letter eng - 014B)\r
-               x (latin small ligature oe - 0153)\r
-               x (greek small letter beta - 03B2)\r
-               x (greek small letter theta - 03B8)\r
-               x (greek small letter lamda - 03BB)\r
-               x (greek small letter chi - 03C7)\r
-0250   LATIN SMALL LETTER TURNED A\r
-       * low central unrounded vowel\r
-0251   LATIN SMALL LETTER ALPHA\r
-       = LATIN SMALL LETTER SCRIPT A\r
-       * low back unrounded vowel\r
-       x (greek small letter alpha - 03B1)\r
-0252   LATIN SMALL LETTER TURNED ALPHA\r
-       * low back rounded vowel\r
-0253   LATIN SMALL LETTER B WITH HOOK\r
-       * implosive bilabial stop\r
-       * Pan-Nigerian alphabet\r
-       x (latin capital letter b with hook - 0181)\r
-0254   LATIN SMALL LETTER OPEN O\r
-       * typographically a turned c\r
-       * lower-mid back rounded vowel\r
-       x (latin capital letter open o - 0186)\r
-0255   LATIN SMALL LETTER C WITH CURL\r
-       * voiceless alveolo-palatal laminal fricative\r
-       * used in transcription of Mandarin Chinese\r
-       * sound spelled with 015B in Polish\r
-0256   LATIN SMALL LETTER D WITH TAIL\r
-       = LATIN SMALL LETTER D RETROFLEX HOOK\r
-       * voiced retroflex stop\r
-       x (latin capital letter african d - 0189)\r
-0257   LATIN SMALL LETTER D WITH HOOK\r
-       * implosive dental or alveolar stop\r
-       * Ewe, Pan-Nigerian alphabet\r
-       x (latin capital letter d with hook - 018A)\r
-0258   LATIN SMALL LETTER REVERSED E\r
-       * upper-mid central unrounded vowel\r
-0259   LATIN SMALL LETTER SCHWA\r
-       * mid-central unrounded vowel\r
-       * variant uppercase form 018E is associated with 01DD\r
-       x (latin capital letter schwa - 018F)\r
-       x (latin small letter turned e - 01DD)\r
-       x (cyrillic small letter schwa - 04D9)\r
-025A   LATIN SMALL LETTER SCHWA WITH HOOK\r
-       * rhotacized schwa\r
-025B   LATIN SMALL LETTER OPEN E\r
-       = LATIN SMALL LETTER EPSILON\r
-       * lower-mid front unrounded vowel\r
-       x (latin capital letter open e - 0190)\r
-       x (greek small letter epsilon - 03B5)\r
-025C   LATIN SMALL LETTER REVERSED OPEN E\r
-       * lower-mid central unrounded vowel\r
-025D   LATIN SMALL LETTER REVERSED OPEN E WITH HOOK\r
-       * rhotacized lower-mid central vowel\r
-025E   LATIN SMALL LETTER CLOSED REVERSED OPEN E\r
-       = LATIN SMALL LETTER CLOSED REVERSED EPSILON\r
-       * lower-mid central rounded vowel\r
-025F   LATIN SMALL LETTER DOTLESS J WITH STROKE\r
-       * voiced palatal stop\r
-       * typographically a turned f, but better thought of as a form of j\r
-       * "gy" in Hungarian orthography\r
-       * also archaic phonetic for palatoalveolar affricate 02A4\r
-0260   LATIN SMALL LETTER G WITH HOOK\r
-       * implosive velar stop\r
-       x (latin capital letter g with hook - 0193)\r
-0261   LATIN SMALL LETTER SCRIPT G\r
-       * voiced velar stop\r
-       x (latin small letter g - 0067)\r
-0262   LATIN LETTER SMALL CAPITAL G\r
-       * voiced uvular stop\r
-0263   LATIN SMALL LETTER GAMMA\r
-       * voiced velar fricative\r
-       x (latin capital letter gamma - 0194)\r
-       x (greek small letter gamma - 03B3)\r
-0264   LATIN SMALL LETTER RAMS HORN\r
-       = LATIN SMALL LETTER BABY GAMMA\r
-       * upper-mid back unrounded vowel\r
-0265   LATIN SMALL LETTER TURNED H\r
-       * voiced rounded palatal approximant\r
-0266   LATIN SMALL LETTER H WITH HOOK\r
-       * breathy-voiced glottal fricative\r
-       x (modifier letter small h with hook - 02B1)\r
-0267   LATIN SMALL LETTER HENG WITH HOOK\r
-       * voiceless coarticulated velar and palatoalveolar fricative\r
-       * "tj" or "kj" or "sj" in some Swedish dialects\r
-0268   LATIN SMALL LETTER I WITH STROKE\r
-       = barred i, i bar\r
-       * high central unrounded vowel\r
-       * ISO 6438 gives lowercase of 0197 as 026A, not 0268\r
-0269   LATIN SMALL LETTER IOTA\r
-       * semi-high front unrounded vowel\r
-@+             * obsoleted by IPA in 1989\r
-       * preferred use is 026A LATIN LETTER SMALL CAPITAL I\r
-       x (latin capital letter iota - 0196)\r
-       x (greek small letter iota - 03B9)\r
-026A   LATIN LETTER SMALL CAPITAL I\r
-       * semi-high front unrounded vowel\r
-       * preferred IPA alternate for 0269\r
-       x (latin capital letter i with stroke - 0197)\r
-026B   LATIN SMALL LETTER L WITH MIDDLE TILDE\r
-       * velarized voiced alveolar lateral approximant\r
-026C   LATIN SMALL LETTER L WITH BELT\r
-       * voiceless alveolar lateral fricative\r
-026D   LATIN SMALL LETTER L WITH RETROFLEX HOOK\r
-       * voiced retroflex lateral\r
-026E   LATIN SMALL LETTER LEZH\r
-       * voiced lateral fricative\r
-       * "dhl" in Zulu orthography\r
-026F   LATIN SMALL LETTER TURNED M\r
-       * high back unrounded vowel\r
-       x (latin capital letter turned m - 019C)\r
-0270   LATIN SMALL LETTER TURNED M WITH LONG LEG\r
-       * voiced velar approximant\r
-0271   LATIN SMALL LETTER M WITH HOOK\r
-       * voiced labiodental nasal\r
-0272   LATIN SMALL LETTER N WITH LEFT HOOK\r
-       * voiced palatal nasal\r
-       x (latin capital letter n with left hook - 019D)\r
-0273   LATIN SMALL LETTER N WITH RETROFLEX HOOK\r
-       * voiced retroflex nasal\r
-0274   LATIN LETTER SMALL CAPITAL N\r
-       * voiced uvular nasal\r
-0275   LATIN SMALL LETTER BARRED O\r
-       = o bar\r
-       * rounded mid-central vowel, i.e. rounded schwa\r
-       * uppercase is 019F\r
-       x (greek small letter theta - 03B8)\r
-       x (cyrillic small letter fita - 0473)\r
-       x (cyrillic small letter barred o - 04E9)\r
-0276   LATIN LETTER SMALL CAPITAL OE\r
-       * low front rounded vowel\r
-       x (latin small ligature oe - 0153)\r
-0277   LATIN SMALL LETTER CLOSED OMEGA\r
-       * semi-high back rounded vowel\r
-@+             * obsoleted by IPA in 1989\r
-       * preferred use is 028A latin small letter upsilon\r
-0278   LATIN SMALL LETTER PHI\r
-       * voiceless bilabial fricative\r
-       x (greek small letter phi - 03C6)\r
-0279   LATIN SMALL LETTER TURNED R\r
-       * voiced alveolar approximant\r
-       x (modifier letter small turned r - 02B4)\r
-027A   LATIN SMALL LETTER TURNED R WITH LONG LEG\r
-       * voiced lateral flap\r
-027B   LATIN SMALL LETTER TURNED R WITH HOOK\r
-       * voiced retroflex approximant\r
-       x (modifier letter small turned r with hook - 02B5)\r
-027C   LATIN SMALL LETTER R WITH LONG LEG\r
-       * voiced strident apico-alveolar trill\r
-@+             * obsoleted by IPA in 1989\r
-       * sound spelled with 0159 in Czech\r
-       * preferred phonetic representation for Czech is 0072 031D\r
-       * in current use in Gaelic types (as glyph variant of 0072)\r
-027D   LATIN SMALL LETTER R WITH TAIL\r
-       * voiced retroflex flap\r
-027E   LATIN SMALL LETTER R WITH FISHHOOK\r
-       * voiced alveolar flap or tap\r
-027F   LATIN SMALL LETTER REVERSED R WITH FISHHOOK\r
-       * apical dental vowel\r
-       * used in Sinological tradition\r
-       * IPA spelling - 007A 0329\r
-0280   LATIN LETTER SMALL CAPITAL R *\r
-       * voiced uvular trill\r
-       * Germanic, Old Norse\r
-       * uppercase is 01A6\r
-0281   LATIN LETTER SMALL CAPITAL INVERTED R\r
-       * voiced uvular fricative or approximant\r
-       x (modifier letter small capital inverted r - 02B6)\r
-0282   LATIN SMALL LETTER S WITH HOOK\r
-       * voiceless retroflex fricative\r
-0283   LATIN SMALL LETTER ESH\r
-       * voiceless postalveolar fricative\r
-       x (latin capital letter esh - 01A9)\r
-       x (integral - 222B)\r
-0284   LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK\r
-       * implosive palatal stop\r
-       * typographically based on 025F, not on 0283\r
-0285   LATIN SMALL LETTER SQUAT REVERSED ESH\r
-       * apical retroflex vowel\r
-       * used in Sinological tradition\r
-       * IPA spelling - 0290 0329\r
-0286   LATIN SMALL LETTER ESH WITH CURL\r
-       * palatalized voiceless postalveolar fricative\r
-       * suggested spelling - 0283 02B2\r
-0287   LATIN SMALL LETTER TURNED T\r
-       * dental click (sound of "tsk tsk")\r
-       x (latin letter dental click - 01C0)\r
-0288   LATIN SMALL LETTER T WITH RETROFLEX HOOK\r
-       * voiceless retroflex stop\r
-       x (latin capital letter t with retroflex hook - 01AE)\r
-0289   LATIN SMALL LETTER U BAR\r
-       * high central rounded vowel\r
-028A   LATIN SMALL LETTER UPSILON\r
-       * semi-high back rounded vowel\r
-       * preferred IPA alternate to 0277\r
-       x (latin capital letter upsilon - 01B1)\r
-       x (greek small letter upsilon - 03C5)\r
-028B   LATIN SMALL LETTER V WITH HOOK\r
-       = LATIN SMALL LETTER SCRIPT V\r
-       * voiced labiodental approximant\r
-       x (latin capital letter v with hook - 01B2)\r
-       x (greek small letter upsilon - 03C5)\r
-028C   LATIN SMALL LETTER TURNED V\r
-       = caret, wedge\r
-       * lower-mid back unrounded vowel\r
-       x (greek capital letter lamda - 039B)\r
-       x (caret - 2038)\r
-       x (logical and - 2227)\r
-028D   LATIN SMALL LETTER TURNED W\r
-       * voiceless rounded labiovelar approximant\r
-028E   LATIN SMALL LETTER TURNED Y\r
-       * voiced lateral approximant\r
-028F   LATIN LETTER SMALL CAPITAL Y\r
-       * semi-high front rounded vowel\r
-0290   LATIN SMALL LETTER Z WITH RETROFLEX HOOK\r
-       * voiced retroflex fricative\r
-0291   LATIN SMALL LETTER Z WITH CURL\r
-       * voiced alveolo-palatal laminal fricative\r
-       * sound spelled with 017A in Polish\r
-0292   LATIN SMALL LETTER EZH\r
-       = LATIN SMALL LETTER YOGH\r
-       = dram\r
-       * voiced postalveolar fricative\r
-       * uppercase is 01B7\r
-       * Skolt Sámi\r
-       x (latin small letter yogh - 021D)\r
-       x (cyrillic small letter abkhasian dze - 04E1)\r
-       x (ounce sign - 2125)\r
-0293   LATIN SMALL LETTER EZH WITH CURL\r
-       * palatalized voiced postalveolar fricative\r
-0294   LATIN LETTER GLOTTAL STOP\r
-       x (modifier letter glottal stop - 02C0)\r
-0295   LATIN LETTER PHARYNGEAL VOICED FRICATIVE\r
-       = LATIN LETTER REVERSED GLOTTAL STOP\r
-       * voiced pharyngeal fricative\r
-       * ain\r
-       x (latin small letter ezh reversed - 01B9)\r
-       x (modifier letter reversed glottal stop - 02C1)\r
-0296   LATIN LETTER INVERTED GLOTTAL STOP\r
-       * lateral click\r
-       x (latin letter lateral click - 01C1)\r
-0297   LATIN LETTER STRETCHED C\r
-       * palatal (or alveolar) click\r
-       x (latin letter retroflex click - 01C3)\r
-       x (complement - 2201)\r
-0298   LATIN LETTER BILABIAL CLICK\r
-       = LATIN LETTER BULLSEYE\r
-       x (circled dot operator - 2299)\r
-0299   LATIN LETTER SMALL CAPITAL B\r
-       * bilabial trill\r
-029A   LATIN SMALL LETTER CLOSED OPEN E\r
-       = LATIN SMALL LETTER CLOSED EPSILON\r
-       * lower-mid front rounded vowel\r
-       * non-IPA alternate for the preferred 0153\r
-029B   LATIN LETTER SMALL CAPITAL G WITH HOOK\r
-       * voiced uvular implosive\r
-029C   LATIN LETTER SMALL CAPITAL H\r
-       * voiceless epiglottal fricative\r
-029D   LATIN SMALL LETTER J WITH CROSSED-TAIL\r
-       * voiced palatal fricative\r
-029E   LATIN SMALL LETTER TURNED K\r
-       * proposed for velar click\r
-@+             * withdrawn by IPA in 1970\r
-029F   LATIN LETTER SMALL CAPITAL L\r
-       * velar lateral approximant\r
-02A0   LATIN SMALL LETTER Q WITH HOOK\r
-       * voiceless uvular implosive\r
-02A1   LATIN LETTER GLOTTAL STOP WITH STROKE\r
-       * voiced epiglottal stop\r
-02A2   LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE\r
-       * voiced epiglottal fricative\r
-02A3   LATIN SMALL LETTER DZ DIGRAPH\r
-       * voiced dental affricate\r
-02A4   LATIN SMALL LETTER DEZH DIGRAPH\r
-       * voiced postalveolar affricate\r
-02A5   LATIN SMALL LETTER DZ DIGRAPH WITH CURL\r
-       * voiced alveolo-palatal affricate\r
-02A6   LATIN SMALL LETTER TS DIGRAPH\r
-       * voiceless dental affricate\r
-02A7   LATIN SMALL LETTER TESH DIGRAPH\r
-       * voiceless postalveolar affricate\r
-02A8   LATIN SMALL LETTER TC DIGRAPH WITH CURL\r
-       * voiceless alveolo-palatal affricate\r
-@              IPA characters for disordered speech\r
-02A9   LATIN SMALL LETTER FENG DIGRAPH\r
-       * velopharyngeal fricative\r
-02AA   LATIN SMALL LETTER LS DIGRAPH\r
-       * lateral alveolar fricative (lisp)\r
-02AB   LATIN SMALL LETTER LZ DIGRAPH\r
-       * voiced lateral alveolar fricative\r
-02AC   LATIN LETTER BILABIAL PERCUSSIVE\r
-       * audible lip smack\r
-02AD   LATIN LETTER BIDENTAL PERCUSSIVE\r
-       * audible teeth gnashing\r
-@@     02B0    Spacing Modifier Letters        02FF\r
-@              Phonetic modifiers derived from Latin letters\r
-02B0   MODIFIER LETTER SMALL H\r
-       * aspiration\r
-       # <super> 0068\r
-02B1   MODIFIER LETTER SMALL H WITH HOOK\r
-       * breathy voiced, murmured\r
-       x (latin small letter h with hook - 0266)\r
-       x (combining diaeresis below - 0324)\r
-       # <super> 0266\r
-02B2   MODIFIER LETTER SMALL J\r
-       * palatalization\r
-       x (combining palatalized hook below - 0321)\r
-       # <super> 006A\r
-02B3   MODIFIER LETTER SMALL R\r
-       # <super> 0072\r
-02B4   MODIFIER LETTER SMALL TURNED R\r
-       x (latin small letter turned r - 0279)\r
-       # <super> 0279\r
-02B5   MODIFIER LETTER SMALL TURNED R WITH HOOK\r
-       x (latin small letter turned r with hook - 027B)\r
-       # <super> 027B\r
-02B6   MODIFIER LETTER SMALL CAPITAL INVERTED R\r
-       * preceding four used for r-coloring or r-offglides\r
-       x (latin letter small capital inverted r - 0281)\r
-       # <super> 0281\r
-02B7   MODIFIER LETTER SMALL W\r
-       * labialization\r
-       x (combining inverted double arch below - 032B)\r
-       # <super> 0077\r
-02B8   MODIFIER LETTER SMALL Y\r
-       * palatalization\r
-       * common Americanist substitution for 02B2\r
-       # <super> 0079\r
-@              Miscellaneous phonetic modifiers\r
-02B9   MODIFIER LETTER PRIME\r
-       * primary stress, emphasis\r
-       * transliteration of mjagkij znak (Cyrillic soft sign: palatalization)\r
-       x (apostrophe - 0027)\r
-       x (acute accent - 00B4)\r
-       x (modifier letter acute accent - 02CA)\r
-       x (combining acute accent - 0301)\r
-       x (greek numeral sign - 0374)\r
-       x (prime - 2032)\r
-02BA   MODIFIER LETTER DOUBLE PRIME\r
-       * exaggerated stress, contrastive stress\r
-       * transliteration of tverdyj znak (Cyrillic hard sign: no palatalization)\r
-       x (quotation mark - 0022)\r
-       x (combining double acute accent - 030B)\r
-       x (double prime - 2033)\r
-02BB   MODIFIER LETTER TURNED COMMA\r
-       * typographical alternate for 02BD or 02BF\r
-       x (combining turned comma above - 0312)\r
-       x (left single quotation mark - 2018)\r
-02BC   MODIFIER LETTER APOSTROPHE\r
-       = apostrophe\r
-       * glottal stop, glottalization, ejective\r
-       * spacing clone of Greek smooth breathing mark\r
-       * many languages use this as a letter of their alphabets\r
-       x (apostrophe - 0027)\r
-       x (combining comma above - 0313)\r
-       x (combining comma above right - 0315)\r
-       x (armenian apostrophe - 055A)\r
-       x (right single quotation mark - 2019)\r
-02BD   MODIFIER LETTER REVERSED COMMA\r
-       * weak aspiration\r
-       * spacing clone of Greek rough breathing mark\r
-       x (combining reversed comma above - 0314)\r
-       x (armenian modifier letter left half ring - 0559)\r
-       x (single high-reversed-9 quotation mark - 201B)\r
-02BE   MODIFIER LETTER RIGHT HALF RING\r
-       * transliteration of Arabic hamza (glottal stop)\r
-       x (armenian apostrophe - 055A)\r
-       x (arabic letter hamza - 0621)\r
-02BF   MODIFIER LETTER LEFT HALF RING\r
-       * transliteration of Arabic ain (voiced pharyngeal fricative)\r
-       x (armenian modifier letter left half ring - 0559)\r
-       x (arabic letter ain - 0639)\r
-02C0   MODIFIER LETTER GLOTTAL STOP\r
-       * ejective or glottalized\r
-       * typographical alternate for 02BC or 02BE\r
-       x (latin letter glottal stop - 0294)\r
-       x (combining hook above - 0309)\r
-02C1   MODIFIER LETTER REVERSED GLOTTAL STOP\r
-       * typographical alternate for 02BF\r
-       x (latin letter pharyngeal voiced fricative - 0295)\r
-02C2   MODIFIER LETTER LEFT ARROWHEAD\r
-       * fronted articulation\r
-02C3   MODIFIER LETTER RIGHT ARROWHEAD\r
-       * backed articulation\r
-02C4   MODIFIER LETTER UP ARROWHEAD\r
-       * raised articulation\r
-       x (circumflex accent - 005E)\r
-       x (up arrowhead - 2303)\r
-02C5   MODIFIER LETTER DOWN ARROWHEAD\r
-       * lowered articulation\r
-02C6   MODIFIER LETTER CIRCUMFLEX ACCENT\r
-       * rising-falling tone, falling tone, secondary stress, etc.\r
-       x (circumflex accent - 005E)\r
-       x (combining circumflex accent - 0302)\r
-02C7   CARON (Mandarin Chinese third tone)\r
-       = hacek\r
-       * falling-rising tone\r
-       * Mandarin Chinese third tone\r
-       x (combining caron - 030C)\r
-02C8   MODIFIER LETTER VERTICAL LINE\r
-       * primary stress, downstep\r
-       * precedes letter or syllable modified\r
-       x (apostrophe - 0027)\r
-       x (combining vertical line above - 030D)\r
-02C9   MODIFIER LETTER MACRON (Mandarin Chinese first tone)\r
-       * high level tone\r
-       * precedes or follows letter or syllable modified\r
-       * Mandarin Chinese first tone\r
-       x (macron - 00AF)\r
-       x (combining macron - 0304)\r
-02CA   MODIFIER LETTER ACUTE ACCENT (Mandarin Chinese second tone)\r
-       * high-rising tone (IPA), high tone, primary stress\r
-       * Mandarin Chinese second tone\r
-       x (acute accent - 00B4)\r
-       x (modifier letter prime - 02B9)\r
-       x (combining acute accent - 0301)\r
-       x (greek numeral sign - 0374)\r
-       x (armenian emphasis mark - 055B)\r
-02CB   MODIFIER LETTER GRAVE ACCENT (Mandarin Chinese fourth tone)\r
-       * high-falling tone (IPA), low tone, secondary or tertiary stress\r
-       * Mandarin Chinese fourth tone\r
-       x (grave accent - 0060)\r
-       x (combining grave accent - 0300)\r
-       x (armenian comma - 055D)\r
-02CC   MODIFIER LETTER LOW VERTICAL LINE\r
-       * secondary stress\r
-       * precedes letter or syllable modified\r
-       x (combining vertical line below - 0329)\r
-02CD   MODIFIER LETTER LOW MACRON\r
-       * low level tone\r
-       x (low line - 005F)\r
-       x (combining macron below - 0331)\r
-02CE   MODIFIER LETTER LOW GRAVE ACCENT\r
-       * low-falling tone\r
-02CF   MODIFIER LETTER LOW ACUTE ACCENT\r
-       * low-rising tone\r
-       x (greek lower numeral sign - 0375)\r
-02D0   MODIFIER LETTER TRIANGULAR COLON\r
-       * length mark\r
-       x (colon - 003A)\r
-02D1   MODIFIER LETTER HALF TRIANGULAR COLON\r
-       * half-length mark\r
-       x (middle dot - 00B7)\r
-02D2   MODIFIER LETTER CENTRED RIGHT HALF RING\r
-       * more rounded articulation\r
-02D3   MODIFIER LETTER CENTRED LEFT HALF RING\r
-       * less rounded articulation\r
-02D4   MODIFIER LETTER UP TACK\r
-       * vowel raising or closing\r
-       x (combining up tack below - 031D)\r
-       x (combining dot below - 0323)\r
-02D5   MODIFIER LETTER DOWN TACK\r
-       * vowel lowering or opening\r
-       x (combining left half ring below - 031C)\r
-       x (combining down tack below - 031E)\r
-02D6   MODIFIER LETTER PLUS SIGN\r
-       * advanced or fronted articulation\r
-       x (combining plus sign below - 031F)\r
-02D7   MODIFIER LETTER MINUS SIGN\r
-       * retracted or backed articulation\r
-       * glyph may have small end-serifs\r
-       x (combining minus sign below - 0320)\r
-@              Spacing clones of diacritics\r
-02D8   BREVE\r
-       x (combining breve - 0306)\r
-       # 0020 0306\r
-02D9   DOT ABOVE (Mandarin Chinese light tone)\r
-       * Mandarin Chinese fifth tone (light or neutral)\r
-       x (combining dot above - 0307)\r
-       # 0020 0307\r
-02DA   RING ABOVE\r
-       x (degree sign - 00B0)\r
-       x (combining ring above - 030A)\r
-       # 0020 030A\r
-02DB   OGONEK\r
-       x (combining ogonek - 0328)\r
-       # 0020 0328\r
-02DC   SMALL TILDE\r
-       x (tilde - 007E)\r
-       x (combining tilde - 0303)\r
-       x (tilde operator - 223C)\r
-       # 0020 0303\r
-02DD   DOUBLE ACUTE ACCENT\r
-       x (combining double acute accent - 030B)\r
-       # 0020 030B\r
-@              Additions based on 1989 IPA\r
-02DE   MODIFIER LETTER RHOTIC HOOK\r
-       * rhotacization in vowel\r
-       * often ligated: 025A = 0259 + 02DE; 025D = 025C + 02DE\r
-02DF   MODIFIER LETTER CROSS ACCENT\r
-       * Swedish grave accent\r
-02E0   MODIFIER LETTER SMALL GAMMA\r
-       * these modifier letters are occasionally used in transcription of affricates\r
-       # <super> 0263\r
-02E1   MODIFIER LETTER SMALL L\r
-       # <super> 006C\r
-02E2   MODIFIER LETTER SMALL S\r
-       # <super> 0073\r
-02E3   MODIFIER LETTER SMALL X\r
-       # <super> 0078\r
-02E4   MODIFIER LETTER SMALL REVERSED GLOTTAL STOP\r
-       # <super> 0295\r
-@              Tone letters\r
-02E5   MODIFIER LETTER EXTRA-HIGH TONE BAR\r
-02E6   MODIFIER LETTER HIGH TONE BAR\r
-02E7   MODIFIER LETTER MID TONE BAR\r
-02E8   MODIFIER LETTER LOW TONE BAR\r
-02E9   MODIFIER LETTER EXTRA-LOW TONE BAR\r
-02EA   MODIFIER LETTER YIN DEPARTING TONE MARK\r
-02EB   MODIFIER LETTER YANG DEPARTING TONE MARK\r
-@              IPA modifiers\r
-02EC   MODIFIER LETTER VOICING\r
-02ED   MODIFIER LETTER UNASPIRATED\r
-@              Other modifier letters\r
-02EE   MODIFIER LETTER DOUBLE APOSTROPHE\r
-\r
-2000   EN QUAD\r
-       : 2002 en space\r
-2001   EM QUAD\r
-       = mutton quad\r
-       : 2003 em space\r
-2002   EN SPACE\r
-       = nut\r
-       * half an em\r
-       # 0020 space\r
-2003   EM SPACE\r
-       = mutton\r
-       * nominally, a space equal to the type size in points\r
-       * may scale by the condensation factor of a font\r
-       # 0020 space\r
-2004   THREE-PER-EM SPACE\r
-       = thick space\r
-       # 0020 space\r
-2005   FOUR-PER-EM SPACE\r
-       = mid space\r
-       # 0020 space\r
-2006   SIX-PER-EM SPACE\r
-       * in computer typography sometimes equated to thin space\r
-       # 0020 space\r
-2007   FIGURE SPACE\r
-       * space equal to tabular width of a font\r
-       * this is equivalent to the digit width of fonts with fixed-width digits\r
-       # <noBreak> 0020\r
-2008   PUNCTUATION SPACE\r
-       * space equal to narrow punctuation of a font\r
-       # 0020 space\r
-2009   THIN SPACE\r
-       * a fifth of an em (or sometimes a sixth)\r
-       # 0020 space\r
-200A   HAIR SPACE\r
-       * thinner than a thin space\r
-       * in traditional typography, the thinnest space available\r
-       # 0020 space\r
-200B   ZERO WIDTH SPACE\r
-       * nominally zero width, but may expand in justification\r
-@              Formatting characters\r
-200C   ZERO WIDTH NON-JOINER\r
-       = ZWNJ\r
-200D   ZERO WIDTH JOINER\r
-       = ZWJ\r
-200E   LEFT-TO-RIGHT MARK\r
-       = LRM\r
-200F   RIGHT-TO-LEFT MARK\r
-       = RLM\r
-@              Dashes\r
-2010   HYPHEN\r
-       x (hyphen-minus - 002D)\r
-2011   NON-BREAKING HYPHEN\r
-       x (hyphen-minus - 002D)\r
-       # <noBreak> 2010\r
-2012   FIGURE DASH\r
-2013   EN DASH\r
-2014   EM DASH\r
-       * may be used in pairs to offset parenthetical text\r
-       x (katakana-hiragana prolonged sound mark - 30FC)\r
-2015   HORIZONTAL BAR\r
-       = QUOTATION DASH\r
-       * long dash introducing quoted text\r
-@              General punctuation\r
-2016   DOUBLE VERTICAL LINE\r
-       * used in pairs to indicate norm of a matrix\r
-       x (parallel to - 2225)\r
-2017   DOUBLE LOW LINE\r
-       * this is a spacing character\r
-       x (low line - 005F)\r
-       x (combining double low line - 0333)\r
-       # 0020 0333\r
-2018   LEFT SINGLE QUOTATION MARK\r
-       = SINGLE TURNED COMMA QUOTATION MARK\r
-       * this is the preferred glyph (as opposed to 201B)\r
-       x (apostrophe - 0027)\r
-       x (modifier letter turned comma - 02BB)\r
-       x (heavy single turned comma quotation mark ornament - 275B)\r
-2019   RIGHT SINGLE QUOTATION MARK\r
-       = SINGLE COMMA QUOTATION MARK\r
-       * this is the preferred character to use for apostrophe\r
-       x (apostrophe - 0027)\r
-       x (modifier letter apostrophe - 02BC)\r
-       x (heavy single comma quotation mark ornament - 275C)\r
-201A   SINGLE LOW-9 QUOTATION MARK\r
-       = LOW SINGLE COMMA QUOTATION MARK\r
-       * used as opening single quotation mark in some languages\r
-201B   SINGLE HIGH-REVERSED-9 QUOTATION MARK\r
-       = SINGLE REVERSED COMMA QUOTATION MARK\r
-       * glyph variant of 2018\r
-       x (modifier letter reversed comma - 02BD)\r
-201C   LEFT DOUBLE QUOTATION MARK\r
-       = DOUBLE TURNED COMMA QUOTATION MARK\r
-       * this is the preferred glyph (as opposed to 201F)\r
-       x (quotation mark - 0022)\r
-       x (heavy double turned comma quotation mark ornament - 275D)\r
-       x (reversed double prime quotation mark - 301D)\r
-201D   RIGHT DOUBLE QUOTATION MARK\r
-       = DOUBLE COMMA QUOTATION MARK\r
-       x (quotation mark - 0022)\r
-       x (double prime - 2033)\r
-       x (heavy double comma quotation mark ornament - 275E)\r
-       x (double prime quotation mark - 301E)\r
-201E   DOUBLE LOW-9 QUOTATION MARK\r
-       = LOW DOUBLE COMMA QUOTATION MARK\r
-       * used as opening double quotation mark in some languages\r
-       x (low double prime quotation mark - 301F)\r
-201F   DOUBLE HIGH-REVERSED-9 QUOTATION MARK\r
-       = DOUBLE REVERSED COMMA QUOTATION MARK\r
-       * glyph variant of 201C\r
-2020   DAGGER\r
-       = obelisk, obelus, long cross\r
-2021   DOUBLE DAGGER\r
-       = diesis, double obelisk\r
-2022   BULLET\r
-       = black small circle\r
-       x (middle dot - 00B7)\r
-       x (one dot leader - 2024)\r
-       x (bullet operator - 2219)\r
-       x (inverse bullet - 25D8)\r
-       x (white bullet - 25E6)\r
-2023   TRIANGULAR BULLET\r
-       x (end of proof - 220E)\r
-       x (black right-pointing small triangle - 25B8)\r
-2024   ONE DOT LEADER\r
-       x (middle dot - 00B7)\r
-       x (bullet - 2022)\r
-       x (bullet operator - 2219)\r
-       # 002E full stop\r
-2025   TWO DOT LEADER\r
-       # 002E 002E\r
-2026   HORIZONTAL ELLIPSIS\r
-       = three dot leader\r
-       x (vertical ellipsis - 22EE)\r
-       # 002E 002E 002E\r
-2027   HYPHENATION POINT\r
-@              Formatting characters\r
-2028   LINE SEPARATOR\r
-       * may be used to represent this semantic unambiguously\r
-2029   PARAGRAPH SEPARATOR\r
-       * may be used to represent this semantic unambiguously\r
-202A   LEFT-TO-RIGHT EMBEDDING\r
-       = LRE\r
-202B   RIGHT-TO-LEFT EMBEDDING\r
-       = RLE\r
-202C   POP DIRECTIONAL FORMATTING\r
-       = PDF\r
-202D   LEFT-TO-RIGHT OVERRIDE\r
-       = LRO\r
-202E   RIGHT-TO-LEFT OVERRIDE\r
-       = RLO\r
-202F   NARROW NO-BREAK SPACE\r
-       x (no-break space - 00A0)\r
-       # <noBreak> 0020\r
-@              General punctuation\r
-2030   PER MILLE SIGN\r
-       x (percent sign - 0025)\r
-2031   PER TEN THOUSAND SIGN\r
-       x (percent sign - 0025)\r
-2032   PRIME\r
-       = minutes, feet\r
-       x (apostrophe - 0027)\r
-       x (acute accent - 00B4)\r
-       x (modifier letter prime - 02B9)\r
-2033   DOUBLE PRIME\r
-       = seconds, inches\r
-       x (quotation mark - 0022)\r
-       x (modifier letter double prime - 02BA)\r
-       x (right double quotation mark - 201D)\r
-       x (ditto mark - 3003)\r
-       x (double prime quotation mark - 301E)\r
-       # 2032 2032\r
-2034   TRIPLE PRIME\r
-       # 2032 2032 2032\r
-2035   REVERSED PRIME\r
-       x (grave accent - 0060)\r
-2036   REVERSED DOUBLE PRIME\r
-       x (reversed double prime quotation mark - 301D)\r
-       # 2035 2035\r
-2037   REVERSED TRIPLE PRIME\r
-       # 2035 2035 2035\r
-2038   CARET\r
-       x (up arrowhead - 2303)\r
-2039   SINGLE LEFT-POINTING ANGLE QUOTATION MARK\r
-       = LEFT POINTING SINGLE GUILLEMET\r
-       * usually opening, sometimes closing\r
-       x (less-than sign - 003C)\r
-       x (left-pointing angle bracket - 2329)\r
-       x (left angle bracket - 3008)\r
-203A   SINGLE RIGHT-POINTING ANGLE QUOTATION MARK\r
-       = RIGHT POINTING SINGLE GUILLEMET\r
-       * usually closing, sometimes opening\r
-       x (greater-than sign - 003E)\r
-       x (right-pointing angle bracket - 232A)\r
-       x (right angle bracket - 3009)\r
-203B   REFERENCE MARK\r
-       = Japanese kome\r
-       = Urdu paragraph separator\r
-       x (tibetan ku ru kha bzhi mig can - 0FBF)\r
-203C   DOUBLE EXCLAMATION MARK\r
-       x (exclamation mark - 0021)\r
-       # 0021 0021\r
-203D   INTERROBANG\r
-       x (exclamation mark - 0021)\r
-       x (question mark - 003F)\r
-203E   OVERLINE\r
-       = SPACING OVERSCORE\r
-       # 0020 0305\r
-203F   UNDERTIE (Enotikon)\r
-       = Greek enotikon\r
-       x (smile - 2323)\r
-2040   CHARACTER TIE\r
-       x (frown - 2322)\r
-2041   CARET INSERTION POINT\r
-       * proofreader's mark: insert here\r
-       x (right semidirect product - 22CC)\r
-2042   ASTERISM\r
-2043   HYPHEN BULLET\r
-2044   FRACTION SLASH\r
-       = solidus (in typography)\r
-       * for composing arbitrary fractions\r
-       x (solidus - 002F)\r
-       x (division slash - 2215)\r
-2045   LEFT SQUARE BRACKET WITH QUILL\r
-2046   RIGHT SQUARE BRACKET WITH QUILL\r
-2048   QUESTION EXCLAMATION MARK\r
-       * designed for use in vertical text\r
-       # 003F 0021\r
-2049   EXCLAMATION QUESTION MARK\r
-       * designed for use in vertical text\r
-       # 0021 003F\r
-204A   TIRONIAN SIGN ET\r
-       * Irish Gaelic, ...\r
-204B   REVERSED PILCROW SIGN\r
-       x (pilcrow sign - 00B6)\r
-204C   BLACK LEFTWARDS BULLET\r
-204D   BLACK RIGHTWARDS BULLET\r
-@              Deprecated\r
-206A   INHIBIT SYMMETRIC SWAPPING\r
-206B   ACTIVATE SYMMETRIC SWAPPING\r
-206C   INHIBIT ARABIC FORM SHAPING\r
-206D   ACTIVATE ARABIC FORM SHAPING\r
-206E   NATIONAL DIGIT SHAPES\r
-206F   NOMINAL DIGIT SHAPES\r
-@@     2070    Superscripts and Subscripts     209F\r
-@              Superscripts\r
-2070   SUPERSCRIPT ZERO\r
-       # <super> 0030\r
-2071   <reserved>\r
-       x (superscript one - 00B9)\r
-2072   <reserved>\r
-       x (superscript two - 00B2)\r
-2073   <reserved>\r
-       x (superscript three - 00B3)\r
-2074   SUPERSCRIPT FOUR\r
-       # <super> 0034\r
-2075   SUPERSCRIPT FIVE\r
-       # <super> 0035\r
-2076   SUPERSCRIPT SIX\r
-       # <super> 0036\r
-2077   SUPERSCRIPT SEVEN\r
-       # <super> 0037\r
-2078   SUPERSCRIPT EIGHT\r
-       # <super> 0038\r
-2079   SUPERSCRIPT NINE\r
-       # <super> 0039\r
-207A   SUPERSCRIPT PLUS SIGN\r
-       # <super> 002B\r
-207B   SUPERSCRIPT MINUS\r
-       # <super> 2212\r
-207C   SUPERSCRIPT EQUALS SIGN\r
-       # <super> 003D\r
-207D   SUPERSCRIPT LEFT PARENTHESIS\r
-       # <super> 0028\r
-207E   SUPERSCRIPT RIGHT PARENTHESIS\r
-       # <super> 0029\r
-207F   SUPERSCRIPT LATIN SMALL LETTER N\r
-       # <super> 006E\r
-@              Subscripts\r
-2080   SUBSCRIPT ZERO\r
-       # <sub> 0030\r
-2081   SUBSCRIPT ONE\r
-       # <sub> 0031\r
-2082   SUBSCRIPT TWO\r
-       # <sub> 0032\r
-2083   SUBSCRIPT THREE\r
-       # <sub> 0033\r
-2084   SUBSCRIPT FOUR\r
-       # <sub> 0034\r
-2085   SUBSCRIPT FIVE\r
-       # <sub> 0035\r
-2086   SUBSCRIPT SIX\r
-       # <sub> 0036\r
-2087   SUBSCRIPT SEVEN\r
-       # <sub> 0037\r
-2088   SUBSCRIPT EIGHT\r
-       # <sub> 0038\r
-2089   SUBSCRIPT NINE\r
-       # <sub> 0039\r
-208A   SUBSCRIPT PLUS SIGN\r
-       # <sub> 002B\r
-208B   SUBSCRIPT MINUS\r
-       # <sub> 2212\r
-208C   SUBSCRIPT EQUALS SIGN\r
-       # <sub> 003D\r
-208D   SUBSCRIPT LEFT PARENTHESIS\r
-       # <sub> 0028\r
-208E   SUBSCRIPT RIGHT PARENTHESIS\r
-       # <sub> 0029\r
-@@     20A0    Currency Symbols        20CF\r
-@              Currency symbols\r
-@+             A number of currency symbols are found in other blocks.\r
-               x (dollar sign - 0024)\r
-               x (cent sign - 00A2)\r
-               x (pound sign - 00A3)\r
-               x (currency sign - 00A4)\r
-               x (yen sign - 00A5)\r
-               x (bengali rupee mark - 09F2)\r
-               x (bengali rupee sign - 09F3)\r
-               x (thai currency symbol baht - 0E3F)\r
-               x (khmer currency symbol riel - 17DB)\r
-20A0   EURO-CURRENCY SIGN\r
-       * intended for ECU, but not widely used\r
-       * historical character, this is NOT the euro!\r
-       x (euro sign - 20AC)\r
-20A1   COLON SIGN\r
-       * Costa Rica, El Salvador\r
-20A2   CRUZEIRO SIGN\r
-       * Brazil\r
-20A3   FRENCH FRANC SIGN\r
-       * France\r
-20A4   LIRA SIGN\r
-       * Italy, Turkey\r
-       x (pound sign - 00A3)\r
-20A5   MILL SIGN\r
-       * USA (1/10 cent)\r
-20A6   NAIRA SIGN\r
-       * Nigeria\r
-20A7   PESETA SIGN\r
-       * Spain\r
-20A8   RUPEE SIGN\r
-       * India\r
-       # 0052 0073\r
-20A9   WON SIGN\r
-       * Korea\r
-20AA   NEW SHEQEL SIGN\r
-       * Israel\r
-20AB   DONG SIGN\r
-       * Vietnam\r
-20AC   EURO SIGN\r
-       * currency sign for the European Monetary Union\r
-       * euro, not ECU\r
-       x (euro-currency sign - 20A0)\r
-20AD   KIP SIGN\r
-       * Laos\r
-20AE   TUGRIK SIGN\r
-       * Mongolia\r
-       * also transliterated as tugrug, tugric, tugrog, togrog\r
-20AF   DRACHMA SIGN\r
-       * Greece\r
-@@     20D0    Combining Diacritical Marks for Symbols 20FF\r
-@              Combining diacritical marks for symbols\r
-20D0   COMBINING LEFT HARPOON ABOVE\r
-20D1   COMBINING RIGHT HARPOON ABOVE\r
-       * vector\r
-20D2   COMBINING LONG VERTICAL LINE OVERLAY\r
-20D3   COMBINING SHORT VERTICAL LINE OVERLAY\r
-       * negation\r
-20D4   COMBINING ANTICLOCKWISE ARROW ABOVE\r
-20D5   COMBINING CLOCKWISE ARROW ABOVE\r
-       * rotation\r
-20D6   COMBINING LEFT ARROW ABOVE\r
-20D7   COMBINING RIGHT ARROW ABOVE\r
-       * vector\r
-20D8   COMBINING RING OVERLAY\r
-20D9   COMBINING CLOCKWISE RING OVERLAY\r
-20DA   COMBINING ANTICLOCKWISE RING OVERLAY\r
-20DB   COMBINING THREE DOTS ABOVE\r
-       = third derivative\r
-20DC   COMBINING FOUR DOTS ABOVE\r
-       = fourth derivative\r
-@              Enclosing diacritics\r
-20DD   COMBINING ENCLOSING CIRCLE\r
-       = JIS composition circle\r
-       x (white circle - 25CB)\r
-       x (large circle - 25EF)\r
-       x (ideographic number zero - 3007)\r
-20DE   COMBINING ENCLOSING SQUARE\r
-       x (white square - 25A1)\r
-20DF   COMBINING ENCLOSING DIAMOND\r
-       x (white diamond - 25C7)\r
-20E0   COMBINING ENCLOSING CIRCLE BACKSLASH\r
-       * prohibition\r
-@              Additional diacritical mark for symbols\r
-20E1   COMBINING LEFT RIGHT ARROW ABOVE\r
-       * tensor\r
-@              Additional enclosing diacritics\r
-20E2   COMBINING ENCLOSING SCREEN\r
-       x (clear screen symbol - 239A)\r
-20E3   COMBINING ENCLOSING KEYCAP\r
-\r
-*/\r
-\r
+//
+// CHARNAMES.CPP
+//
+// A header file that links Unicode character names to character numbers.
+// by James L. Hammons
+// (C) 2004 Underground Software
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  ??/??/200?  Created this file
+//
+
+unsigned char macStdNames[] = {
+  "\x06""notdef"
+  "\x05"".null"
+  "\x02""CR"
+  "\x05""space"
+  "\x06""exclam"
+  "\x08""quotedbl"
+  "\x0A""numbersign"
+  "\x06""dollar"
+  "\x07""percent"
+  "\x09""ampersand"
+  "\x0B""quotesingle"
+  "\x09""parenleft"
+  "\x0A""parenright"
+  "\x08""asterisk"
+  "\x04""plus"
+  "\x05""comma"
+  "\x06""hyphen"
+  "\x06""period"
+  "\x05""slash"
+  "\x04""zero"
+  "\x03""one"
+  "\x03""two"
+  "\x05""three"
+  "\x04""four"
+  "\x04""five"
+  "\x03""six"
+  "\x05""seven"
+  "\x05""eight"
+  "\x04""nine"
+  "\x05""colon"
+  "\x09""semicolon"
+  "\x04""less"
+  "\x05""equal"
+  "\x07""greater"
+  "\x08""question"
+  "\x02""at"
+  "\x01""A"
+  "\x01""B"
+  "\x01""C"
+  "\x01""D"
+  "\x01""E"
+  "\x01""F"
+  "\x01""G"
+  "\x01""H"
+  "\x01""I"
+  "\x01""J"
+  "\x01""K"
+  "\x01""L"
+  "\x01""M"
+  "\x01""N"
+  "\x01""O"
+  "\x01""P"
+  "\x01""Q"
+  "\x01""R"
+  "\x01""S"
+  "\x01""T"
+  "\x01""U"
+  "\x01""V"
+  "\x01""W"
+  "\x01""X"
+  "\x01""Y"
+  "\x01""Z"
+  "\x0B""bracketleft"
+  "\x09""backslash"
+  "\x0C""bracketright"
+  "\x0B""asciicircum"
+  "\x0A""underscore"
+  "\x05""grave"
+  "\x01""a"
+  "\x01""b"
+  "\x01""c"
+  "\x01""d"
+  "\x01""e"
+  "\x01""f"
+  "\x01""g"
+  "\x01""h"
+  "\x01""i"
+  "\x01""j"
+  "\x01""k"
+  "\x01""l"
+  "\x01""m"
+  "\x01""n"
+  "\x01""o"
+  "\x01""p"
+  "\x01""q"
+  "\x01""r"
+  "\x01""s"
+  "\x01""t"
+  "\x01""u"
+  "\x01""v"
+  "\x01""w"
+  "\x01""x"
+  "\x01""y"
+  "\x01""z"
+  "\x09""braceleft"
+  "\x03""bar"
+  "\x0A""braceright"
+  "\x0A""asciitilde"
+  "\x09""Adieresis"
+  "\x05""Aring"
+  "\x08""Ccedilla"
+  "\x06""Eacute"
+  "\x06""Ntilde"
+  "\x09""Odieresis"
+  "\x09""Udieresis"
+  "\x06""aacute"
+  "\x06""agrave"
+  "\x0B""acircumflex"
+  "\x09""adieresis"
+  "\x06""atilde"
+  "\x05""aring"
+  "\x08""ccedilla"
+  "\x06""eacute"
+  "\x06""egrave"
+  "\x0B""ecircumflex"
+  "\x09""edieresis"
+  "\x06""iacute"
+  "\x06""igrave"
+  "\x0B""icircumflex"
+  "\x09""idieresis"
+  "\x06""ntilde"
+  "\x06""oacute"
+  "\x06""ograve"
+  "\x0B""ocircumflex"
+  "\x09""odieresis"
+  "\x06""otilde"
+  "\x06""uacute"
+  "\x06""ugrave"
+  "\x0B""ucircumflex"
+  "\x09""udieresis"
+  "\x06""dagger"
+  "\x06""degree"
+  "\x04""cent"
+  "\x08""sterling"
+  "\x07""section"
+  "\x06""bullet"
+  "\x09""paragraph"
+  "\x0A""germandbls"
+  "\x0A""registered"
+  "\x09""copyright"
+  "\x09""trademark"
+  "\x05""acute"
+  "\x08""dieresis"
+  "\x08""notequal"
+  "\x02""AE"
+  "\x06""Oslash"
+  "\x08""infinity"
+  "\x09""plusminus"
+  "\x09""lessequal"
+  "\x0C""greaterequal"
+  "\x03""yen"
+  "\x03""mu1"
+  "\x0B""partialdiff"
+  "\x09""summation"
+  "\x07""product"
+  "\x02""pi"
+  "\x08""integral"
+  "\x0B""ordfeminine"
+  "\x0C""ordmasculine"
+  "\x03""Ohm"
+  "\x02""ae"
+  "\x06""oslash"
+  "\x0C""questiondown"
+  "\x0A""exclamdown"
+  "\x0A""logicalnot"
+  "\x07""radical"
+  "\x06""florin"
+  "\x0B""approxequal"
+  "\x09""increment"
+  "\x0D""guillemotleft"
+  "\x0E""guillemotright"
+  "\x08""ellipsis"
+  "\x07""nbspace"
+  "\x06""Agrave"
+  "\x06""Atilde"
+  "\x06""Otilde"
+  "\x02""OE"
+  "\x02""oe"
+  "\x06""endash"
+  "\x06""emdash"
+  "\x0C""quotedblleft"
+  "\x0D""quotedblright"
+  "\x09""quoteleft"
+  "\x0A""quoteright"
+  "\x06""divide"
+  "\x07""lozenge"
+  "\x09""ydieresis"
+  "\x09""Ydieresis"
+  "\x08""fraction"
+  "\x08""currency"
+  "\x0D""guilsinglleft"
+  "\x0E""guilsinglright"
+  "\x02""fi"
+  "\x02""fl"
+  "\x09""daggerdbl"
+  "\x0E""periodcentered"
+  "\x0E""quotesinglbase"
+  "\x0C""quotedblbase"
+  "\x0B""perthousand"
+  "\x0B""Acircumflex"
+  "\x0B""Ecircumflex"
+  "\x06""Aacute"
+  "\x09""Edieresis"
+  "\x06""Egrave"
+  "\x06""Iacute"
+  "\x0B""Icircumflex"
+  "\x09""Idieresis"
+  "\x06""Igrave"
+  "\x06""Oacute"
+  "\x0B""Ocircumflex"
+  "\x09""applelogo"
+  "\x06""Ograve"
+  "\x06""Uacute"
+  "\x0B""Ucircumflex"
+  "\x06""Ugrave"
+  "\x08""dotlessi"
+  "\x0A""circumflex"
+  "\x05""tilde"
+  "\x09""overscore"
+  "\x05""breve"
+  "\x09""dotaccent"
+  "\x04""ring"
+  "\x07""cedilla"
+  "\x0C""hungarumlaut"
+  "\x06""ogonek"
+  "\x05""caron"
+  "\x06""Lslash"
+  "\x06""lslash"
+  "\x06""Scaron"
+  "\x06""scaron"
+  "\x06""Zcaron"
+  "\x06""zcaron"
+  "\x09""brokenbar"
+  "\x03""Eth"
+  "\x03""eth"
+  "\x06""Yacute"
+  "\x06""yacute"
+  "\x05""Thorn"
+  "\x05""thorn"
+  "\x05""minus"
+  "\x08""multiply"
+  "\x0B""onesuperior"
+  "\x0B""twosuperior"
+  "\x0D""threesuperior"
+  "\x07""onehalf"
+  "\x0A""onequarter"
+  "\x0D""threequarters"
+  "\x05""franc"
+  "\x06""Gbreve"
+  "\x06""gbreve"
+  "\x04""Idot"
+  "\x08""Scedilla"
+  "\x08""scedilla"
+  "\x06""Cacute"
+  "\x06""cacute"
+  "\x06""Ccaron"
+  "\x06""ccaron"
+  "\x07""dmacron"
+};
+
+/*struct unicodeChar
+{
+  int cNum;
+
+};*/
+
+unsigned char unicodeChars[] = {
+  "\x00\x20""space\0"
+  "\x00\x21""exclamation mark\0"
+  "\x00\x22""quotation mark\0"
+  "\x00\x23""number sign\0"
+
+};
+
+/*
+
+0023   NUMBER SIGN
+       = pound sign, hash, crosshatch, octothorpe
+0024   DOLLAR SIGN
+       = milreis, escudo
+       * glyph may have one or two vertical bars
+       * other currency symbol characters: 20A0-20AF
+       x (currency sign - 00A4)
+0025   PERCENT SIGN
+       x (arabic percent sign - 066A)
+       x (per mille sign - 2030)
+       x (per ten thousand sign - 2031)
+0026   AMPERSAND
+0027   APOSTROPHE
+       = APOSTROPHE-QUOTE
+       = APL quote
+       * neutral (vertical) glyph having mixed usage
+       * preferred character for apostrophe is 2019
+       * preferred characters in English for paired quotation marks are 2018 & 2019
+       x (modifier letter prime - 02B9)
+       x (modifier letter apostrophe - 02BC)
+       x (modifier letter vertical line - 02C8)
+       x (combining acute accent - 0301)
+       x (prime - 2032)
+0028   LEFT PARENTHESIS
+       = OPENING PARENTHESIS
+0029   RIGHT PARENTHESIS
+       = CLOSING PARENTHESIS
+       * see discussion on semantics of paired bracketing characters
+002A   ASTERISK
+       = star (on phone keypads)
+       x (arabic five pointed star - 066D)
+       x (asterisk operator - 2217)
+       x (heavy asterisk - 2731)
+002B   PLUS SIGN
+002C   COMMA
+       = decimal separator
+       x (arabic comma - 060C)
+       x (single low-9 quotation mark - 201A)
+       x (ideographic comma - 3001)
+002D   HYPHEN-MINUS
+       = hyphen or minus sign
+       * used for either hyphen or minus sign
+       x (hyphen - 2010)
+       x (non-breaking hyphen - 2011)
+       x (figure dash - 2012)
+       x (en dash - 2013)
+       x (minus sign - 2212)
+002E   FULL STOP
+       = PERIOD
+       = dot, decimal point
+       * may be rendered as a raised decimal point in old style numbers
+       x (arabic full stop - 06D4)
+       x (ideographic full stop - 3002)
+002F   SOLIDUS
+       = SLASH
+       = virgule, shilling (British)
+       x (latin letter dental click - 01C0)
+       x (combining long solidus overlay - 0338)
+       x (fraction slash - 2044)
+       x (division slash - 2215)
+0030   DIGIT ZERO
+0031   DIGIT ONE
+0032   DIGIT TWO
+0033   DIGIT THREE
+0034   DIGIT FOUR
+0035   DIGIT FIVE
+0036   DIGIT SIX
+0037   DIGIT SEVEN
+0038   DIGIT EIGHT
+0039   DIGIT NINE
+003A   COLON
+       x (armenian full stop - 0589)
+       x (hebrew punctuation sof pasuq - 05C3)
+       x (ratio - 2236)
+003B   SEMICOLON
+       x (greek question mark - 037E)
+       x (arabic semicolon - 061B)
+003C   LESS-THAN SIGN
+       x (single left-pointing angle quotation mark - 2039)
+       x (left-pointing angle bracket - 2329)
+       x (left angle bracket - 3008)
+003D   EQUALS SIGN
+       * other related characters: 2241-2263
+       x (not equal to - 2260)
+       x (identical to - 2261)
+003E   GREATER-THAN SIGN
+       x (single right-pointing angle quotation mark - 203A)
+       x (right-pointing angle bracket - 232A)
+       x (right angle bracket - 3009)
+003F   QUESTION MARK
+       x (inverted question mark - 00BF)
+       x (greek question mark - 037E)
+       x (arabic question mark - 061F)
+       x (interrobang - 203D)
+       x (question exclamation mark - 2048)
+       x (exclamation question mark - 2049)
+0040   COMMERCIAL AT
+0041   LATIN CAPITAL LETTER A
+0042   LATIN CAPITAL LETTER B
+       x (script capital b - 212C)
+0043   LATIN CAPITAL LETTER C
+       x (double-struck capital c - 2102)
+       x (black-letter capital c - 212D)
+0044   LATIN CAPITAL LETTER D
+0045   LATIN CAPITAL LETTER E
+       x (euler constant - 2107)
+       x (script capital e - 2130)
+0046   LATIN CAPITAL LETTER F
+       x (script capital f - 2131)
+       x (turned capital f - 2132)
+0047   LATIN CAPITAL LETTER G
+0048   LATIN CAPITAL LETTER H
+       x (script capital h - 210B)
+       x (black-letter capital h - 210C)
+       x (double-struck capital h - 210D)
+0049   LATIN CAPITAL LETTER I
+       * Turkish and Azerbaijani use 0131 for lowercase
+       x (latin capital letter i with dot above - 0130)
+       x (cyrillic capital letter byelorussian-ukrainian i - 0406)
+       x (cyrillic letter palochka - 04C0)
+       x (script capital i - 2110)
+       x (black-letter capital i - 2111)
+       x (roman numeral one - 2160)
+004A   LATIN CAPITAL LETTER J
+004B   LATIN CAPITAL LETTER K
+       x (kelvin sign - 212A)
+004C   LATIN CAPITAL LETTER L
+       x (script capital l - 2112)
+004D   LATIN CAPITAL LETTER M
+       x (script capital m - 2133)
+004E   LATIN CAPITAL LETTER N
+       x (double-struck capital n - 2115)
+004F   LATIN CAPITAL LETTER O
+0050   LATIN CAPITAL LETTER P
+       x (double-struck capital p - 2119)
+0051   LATIN CAPITAL LETTER Q
+       x (double-struck capital q - 211A)
+0052   LATIN CAPITAL LETTER R
+       x (script capital r - 211B)
+       x (black-letter capital r - 211C)
+       x (double-struck capital r - 211D)
+0053   LATIN CAPITAL LETTER S
+0054   LATIN CAPITAL LETTER T
+0055   LATIN CAPITAL LETTER U
+0056   LATIN CAPITAL LETTER V
+0057   LATIN CAPITAL LETTER W
+0058   LATIN CAPITAL LETTER X
+0059   LATIN CAPITAL LETTER Y
+005A   LATIN CAPITAL LETTER Z
+       x (double-struck capital z - 2124)
+       x (black-letter capital z - 2128)
+005B   LEFT SQUARE BRACKET
+       = OPENING SQUARE BRACKET
+       * other bracket characters: 3008-301B
+005C   REVERSE SOLIDUS
+       = BACKSLASH
+       x (set minus - 2216)
+005D   RIGHT SQUARE BRACKET
+       = CLOSING SQUARE BRACKET
+005E   CIRCUMFLEX ACCENT
+       * this is a spacing character
+       x (modifier letter up arrowhead - 02C4)
+       x (modifier letter circumflex accent - 02C6)
+       x (combining circumflex accent - 0302)
+       x (up arrowhead - 2303)
+005F   LOW LINE
+       = SPACING UNDERSCORE
+       * this is a spacing character
+       x (modifier letter low macron - 02CD)
+       x (combining macron below - 0331)
+       x (combining low line - 0332)
+       x (double low line - 2017)
+0060   GRAVE ACCENT
+       * this is a spacing character
+       x (modifier letter grave accent - 02CB)
+       x (combining grave accent - 0300)
+       x (reversed prime - 2035)
+0061   LATIN SMALL LETTER A
+0062   LATIN SMALL LETTER B
+0063   LATIN SMALL LETTER C
+0064   LATIN SMALL LETTER D
+0065   LATIN SMALL LETTER E
+       x (estimated symbol - 212E)
+       x (script small e - 212F)
+0066   LATIN SMALL LETTER F
+0067   LATIN SMALL LETTER G
+       x (latin small letter script g - 0261)
+       x (script small g - 210A)
+0068   LATIN SMALL LETTER H
+       x (cyrillic small letter shha - 04BB)
+       x (planck constant - 210E)
+0069   LATIN SMALL LETTER I
+       * Turkish and Azerbaijani use 0130 for uppercase
+       x (latin small letter dotless i - 0131)
+006A   LATIN SMALL LETTER J
+006B   LATIN SMALL LETTER K
+006C   LATIN SMALL LETTER L
+       x (script small l - 2113)
+006D   LATIN SMALL LETTER M
+006E   LATIN SMALL LETTER N
+       x (superscript latin small letter n - 207F)
+006F   LATIN SMALL LETTER O
+       x (script small o - 2134)
+0070   LATIN SMALL LETTER P
+0071   LATIN SMALL LETTER Q
+0072   LATIN SMALL LETTER R
+0073   LATIN SMALL LETTER S
+0074   LATIN SMALL LETTER T
+0075   LATIN SMALL LETTER U
+0076   LATIN SMALL LETTER V
+0077   LATIN SMALL LETTER W
+0078   LATIN SMALL LETTER X
+0079   LATIN SMALL LETTER Y
+007A   LATIN SMALL LETTER Z
+       x (latin small letter z with stroke - 01B6)
+007B   LEFT CURLY BRACKET
+       = OPENING CURLY BRACKET
+       = opening brace
+007C   VERTICAL LINE
+       = VERTICAL BAR
+       * used in pairs to indicate absolute value
+       x (latin letter dental click - 01C0)
+       x (hebrew punctuation paseq - 05C0)
+       x (divides - 2223)
+       x (light vertical bar - 2758)
+007D   RIGHT CURLY BRACKET
+       = CLOSING CURLY BRACKET
+       = closing brace
+007E   TILDE
+       * this is a spacing character
+       x (small tilde - 02DC)
+       x (combining tilde - 0303)
+       x (tilde operator - 223C)
+       x (fullwidth tilde - FF5E)
+007F   <control>
+       = DELETE
+@@     0080    C1 Controls and Latin-1 Supplement (Latin-1 Supplement) 00FF
+@              C1 controls
+@+             Alias names are those for ISO 6429.
+0080   <control>
+0081   <control>
+0082   <control>
+       = BREAK PERMITTED HERE
+0083   <control>
+       = NO BREAK HERE
+0084   <control>
+0085   <control>
+       = NEXT LINE
+0086   <control>
+       = START OF SELECTED AREA
+0087   <control>
+       = END OF SELECTED AREA
+0088   <control>
+       = CHARACTER TABULATION SET
+0089   <control>
+       = CHARACTER TABULATION WITH JUSTIFICATION
+008A   <control>
+       = LINE TABULATION SET
+008B   <control>
+       = PARTIAL LINE DOWN
+008C   <control>
+       = PARTIAL LINE UP
+008D   <control>
+       = REVERSE LINE FEED
+008E   <control>
+       = SINGLE SHIFT TWO
+008F   <control>
+       = SINGLE SHIFT THREE
+0090   <control>
+       = DEVICE CONTROL STRING
+0091   <control>
+       = PRIVATE USE ONE
+0092   <control>
+       = PRIVATE USE TWO
+0093   <control>
+       = SET TRANSMIT STATE
+0094   <control>
+       = CANCEL CHARACTER
+0095   <control>
+       = MESSAGE WAITING
+0096   <control>
+       = START OF GUARDED AREA
+0097   <control>
+       = END OF GUARDED AREA
+0098   <control>
+       = START OF STRING
+0099   <control>
+009A   <control>
+       = SINGLE CHARACTER INTRODUCER
+009B   <control>
+       = CONTROL SEQUENCE INTRODUCER
+009C   <control>
+       = STRING TERMINATOR
+009D   <control>
+       = OPERATING SYSTEM COMMAND
+009E   <control>
+       = PRIVACY MESSAGE
+009F   <control>
+       = APPLICATION PROGRAM COMMAND
+@              ISO 8859-1 (aka Latin-1)
+00A0   NO-BREAK SPACE
+       x (space - 0020)
+       x (figure space - 2007)
+       x (narrow no-break space - 202F)
+       x (zero width no-break space - FEFF)
+       # <noBreak> 0020
+00A1   INVERTED EXCLAMATION MARK
+       * Spanish, Asturian, Galician
+       x (exclamation mark - 0021)
+00A2   CENT SIGN
+00A3   POUND SIGN
+       = pound sterling, Irish punt
+       x (lira sign - 20A4)
+00A4   CURRENCY SIGN
+       = Filzlaus, Ricardi-Sonne (German names)
+       * other currency symbol characters: 20A0-20AF
+       x (dollar sign - 0024)
+00A5   YEN SIGN
+       = yuan sign
+       * glyph may have one or two crossbars
+00A6   BROKEN BAR
+       = BROKEN VERTICAL BAR
+       = parted rule (in typography)
+00A7   SECTION SIGN
+       * paragraph sign in some European usage
+00A8   DIAERESIS
+       * this is a spacing character
+       x (combining diaeresis - 0308)
+       # 0020 0308
+00A9   COPYRIGHT SIGN
+       x (sound recording copyright - 2117)
+00AA   FEMININE ORDINAL INDICATOR
+       * Spanish
+       # <super> 0061
+00AB   LEFT-POINTING DOUBLE ANGLE QUOTATION MARK *
+       = LEFT POINTING GUILLEMET
+       = chevrons (in typography)
+       * usually opening, sometimes closing
+       x (much less-than - 226A)
+       x (left double angle bracket - 300A)
+00AC   NOT SIGN
+       = angled dash (in typography)
+       x (reversed not sign - 2310)
+00AD   SOFT HYPHEN
+       = discretionary hyphen
+       x (mongolian todo soft hyphen - 1806)
+00AE   REGISTERED SIGN
+       = REGISTERED TRADE MARK SIGN
+00AF   MACRON
+       = overline, APL overbar
+       * this is a spacing character
+       x (modifier letter macron - 02C9)
+       x (combining macron - 0304)
+       x (combining overline - 0305)
+       # 0020 0304
+00B0   DEGREE SIGN
+       * this is a spacing character
+       x (ring above - 02DA)
+       x (combining ring above - 030A)
+       x (superscript zero - 2070)
+       x (ring operator - 2218)
+00B1   PLUS-MINUS SIGN
+       x (minus-or-plus sign - 2213)
+00B2   SUPERSCRIPT TWO
+       = squared
+       * other superscript digit characters: 2070-2079
+       x (superscript one - 00B9)
+       # <super> 0032
+00B3   SUPERSCRIPT THREE
+       = cubed
+       x (superscript one - 00B9)
+       # <super> 0033
+00B4   ACUTE ACCENT
+       * this is a spacing character
+       x (modifier letter prime - 02B9)
+       x (modifier letter acute accent - 02CA)
+       x (combining acute accent - 0301)
+       x (prime - 2032)
+       # 0020 0301
+00B5   MICRO SIGN
+       # 03BC greek small letter mu
+00B6   PILCROW SIGN
+       = PARAGRAPH SIGN
+       * section sign in some European usage
+       x (reversed pilcrow sign - 204B)
+       x (curved stem paragraph sign ornament - 2761)
+00B7   MIDDLE DOT
+       = midpoint (in typography)
+       = Georgian comma
+       = Greek middle dot
+       x (bullet - 2022)
+       x (one dot leader - 2024)
+       x (hyphenation point - 2027)
+       x (bullet operator - 2219)
+       x (dot operator - 22C5)
+       x (katakana middle dot - 30FB)
+00B8   CEDILLA
+       * this is a spacing character
+       * other spacing accent characters: 02D8-02DB
+       x (combining cedilla - 0327)
+       # 0020 0327
+00B9   SUPERSCRIPT ONE
+       x (superscript two - 00B2)
+       x (superscript three - 00B3)
+       # <super> 0031
+00BA   MASCULINE ORDINAL INDICATOR
+       * Spanish
+       # <super> 006F
+00BB   RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK *
+       = RIGHT POINTING GUILLEMET
+       * usually closing, sometimes opening
+       x (much greater-than - 226B)
+       x (right double angle bracket - 300B)
+00BC   VULGAR FRACTION ONE QUARTER
+       * bar may be horizontal or slanted
+       * other fraction characters: 2153-215E
+       # 0031 2044 0034
+00BD   VULGAR FRACTION ONE HALF
+       * bar may be horizontal or slanted
+       # 0031 2044 0032
+00BE   VULGAR FRACTION THREE QUARTERS
+       * bar may be horizontal or slanted
+       # 0033 2044 0034
+00BF   INVERTED QUESTION MARK
+       = turned question mark
+       * Spanish
+       x (question mark - 003F)
+00C0   LATIN CAPITAL LETTER A WITH GRAVE
+       : 0041 0300
+00C1   LATIN CAPITAL LETTER A WITH ACUTE
+       : 0041 0301
+00C2   LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+       : 0041 0302
+00C3   LATIN CAPITAL LETTER A WITH TILDE
+       : 0041 0303
+00C4   LATIN CAPITAL LETTER A WITH DIAERESIS
+       : 0041 0308
+00C5   LATIN CAPITAL LETTER A WITH RING ABOVE
+       x (angstrom sign - 212B)
+       : 0041 030A
+00C6   LATIN CAPITAL LETTER AE (ash) *
+       = LATIN CAPITAL LIGATURE AE
+00C7   LATIN CAPITAL LETTER C WITH CEDILLA
+       : 0043 0327
+00C8   LATIN CAPITAL LETTER E WITH GRAVE
+       : 0045 0300
+00C9   LATIN CAPITAL LETTER E WITH ACUTE
+       : 0045 0301
+00CA   LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+       : 0045 0302
+00CB   LATIN CAPITAL LETTER E WITH DIAERESIS
+       : 0045 0308
+00CC   LATIN CAPITAL LETTER I WITH GRAVE
+       : 0049 0300
+00CD   LATIN CAPITAL LETTER I WITH ACUTE
+       : 0049 0301
+00CE   LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+       : 0049 0302
+00CF   LATIN CAPITAL LETTER I WITH DIAERESIS
+       : 0049 0308
+00D0   LATIN CAPITAL LETTER ETH (Icelandic)
+       x (latin small letter eth - 00F0)
+       x (latin capital letter d with stroke - 0110)
+       x (latin capital letter african d - 0189)
+00D1   LATIN CAPITAL LETTER N WITH TILDE
+       : 004E 0303
+00D2   LATIN CAPITAL LETTER O WITH GRAVE
+       : 004F 0300
+00D3   LATIN CAPITAL LETTER O WITH ACUTE
+       : 004F 0301
+00D4   LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+       : 004F 0302
+00D5   LATIN CAPITAL LETTER O WITH TILDE
+       : 004F 0303
+00D6   LATIN CAPITAL LETTER O WITH DIAERESIS
+       : 004F 0308
+00D7   MULTIPLICATION SIGN
+       = z notation Cartesian product
+00D8   LATIN CAPITAL LETTER O WITH STROKE
+       = LATIN CAPITAL LETTER O SLASH
+       x (empty set - 2205)
+00D9   LATIN CAPITAL LETTER U WITH GRAVE
+       : 0055 0300
+00DA   LATIN CAPITAL LETTER U WITH ACUTE
+       : 0055 0301
+00DB   LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+       : 0055 0302
+00DC   LATIN CAPITAL LETTER U WITH DIAERESIS
+       : 0055 0308
+00DD   LATIN CAPITAL LETTER Y WITH ACUTE
+       : 0059 0301
+00DE   LATIN CAPITAL LETTER THORN (Icelandic)
+00DF   LATIN SMALL LETTER SHARP S (German)
+       = Eszett
+       * German
+       * uppercase is "SS"
+       * in origin a ligature of 017F and 0073
+       x (greek small letter beta - 03B2)
+00E0   LATIN SMALL LETTER A WITH GRAVE
+       : 0061 0300
+00E1   LATIN SMALL LETTER A WITH ACUTE
+       : 0061 0301
+00E2   LATIN SMALL LETTER A WITH CIRCUMFLEX
+       : 0061 0302
+00E3   LATIN SMALL LETTER A WITH TILDE
+       * Portuguese
+       : 0061 0303
+00E4   LATIN SMALL LETTER A WITH DIAERESIS
+       : 0061 0308
+00E5   LATIN SMALL LETTER A WITH RING ABOVE
+       * Danish, Norwegian, Swedish, Walloon
+       : 0061 030A
+00E6   LATIN SMALL LETTER AE (ash) *
+       = LATIN SMALL LIGATURE AE
+       = ash (from Old English Ã¦sc)
+       * Danish, Norwegian, Icelandic, Faroese, Old English, French, IPA
+       x (latin small ligature oe - 0153)
+       x (cyrillic small ligature a ie - 04D5)
+00E7   LATIN SMALL LETTER C WITH CEDILLA
+       : 0063 0327
+00E8   LATIN SMALL LETTER E WITH GRAVE
+       : 0065 0300
+00E9   LATIN SMALL LETTER E WITH ACUTE
+       : 0065 0301
+00EA   LATIN SMALL LETTER E WITH CIRCUMFLEX
+       : 0065 0302
+00EB   LATIN SMALL LETTER E WITH DIAERESIS
+       : 0065 0308
+00EC   LATIN SMALL LETTER I WITH GRAVE
+       * Italian, Malagasy
+       : 0069 0300
+00ED   LATIN SMALL LETTER I WITH ACUTE
+       : 0069 0301
+00EE   LATIN SMALL LETTER I WITH CIRCUMFLEX
+       : 0069 0302
+00EF   LATIN SMALL LETTER I WITH DIAERESIS
+       : 0069 0308
+00F0   LATIN SMALL LETTER ETH (Icelandic)
+       * Icelandic, Faroese, Old English, IPA
+       x (latin capital letter eth - 00D0)
+       x (greek small letter delta - 03B4)
+       x (partial differential - 2202)
+00F1   LATIN SMALL LETTER N WITH TILDE
+       : 006E 0303
+00F2   LATIN SMALL LETTER O WITH GRAVE
+       : 006F 0300
+00F3   LATIN SMALL LETTER O WITH ACUTE
+       : 006F 0301
+00F4   LATIN SMALL LETTER O WITH CIRCUMFLEX
+       : 006F 0302
+00F5   LATIN SMALL LETTER O WITH TILDE
+       * Portuguese, Estonian
+       : 006F 0303
+00F6   LATIN SMALL LETTER O WITH DIAERESIS
+       : 006F 0308
+00F7   DIVISION SIGN
+00F8   LATIN SMALL LETTER O WITH STROKE
+       = LATIN SMALL LETTER O SLASH
+       * Danish, Norwegian, Faroese, IPA
+00F9   LATIN SMALL LETTER U WITH GRAVE
+       * French, Italian
+       : 0075 0300
+00FA   LATIN SMALL LETTER U WITH ACUTE
+       : 0075 0301
+00FB   LATIN SMALL LETTER U WITH CIRCUMFLEX
+       : 0075 0302
+00FC   LATIN SMALL LETTER U WITH DIAERESIS
+       : 0075 0308
+00FD   LATIN SMALL LETTER Y WITH ACUTE
+       * Czech, Slovak, Icelandic, Faroese, Welsh, Malagasy
+       : 0079 0301
+00FE   LATIN SMALL LETTER THORN (Icelandic)
+       * Icelandic, Old English, phonetics
+       * Runic letter borrowed into Latin script
+       x (runic letter thurisaz thurs thorn - 16A6)
+00FF   LATIN SMALL LETTER Y WITH DIAERESIS
+       * French
+       x (latin capital letter y with diaeresis - 0178)
+       : 0079 0308
+@@     0100    Latin Extended-A        017F
+@              European Latin
+0100   LATIN CAPITAL LETTER A WITH MACRON
+       : 0041 0304
+0101   LATIN SMALL LETTER A WITH MACRON
+       * Latvian, Latin, ...
+       : 0061 0304
+0102   LATIN CAPITAL LETTER A WITH BREVE
+       : 0041 0306
+0103   LATIN SMALL LETTER A WITH BREVE
+       * Romanian, Vietnamese, Latin, ...
+       : 0061 0306
+0104   LATIN CAPITAL LETTER A WITH OGONEK
+       : 0041 0328
+0105   LATIN SMALL LETTER A WITH OGONEK
+       * Polish, Lithuanian, ...
+       : 0061 0328
+0106   LATIN CAPITAL LETTER C WITH ACUTE
+       : 0043 0301
+0107   LATIN SMALL LETTER C WITH ACUTE
+       * Polish, Croatian, ...
+       x (cyrillic small letter tshe - 045B)
+       : 0063 0301
+0108   LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+       : 0043 0302
+0109   LATIN SMALL LETTER C WITH CIRCUMFLEX
+       * Esperanto
+       : 0063 0302
+010A   LATIN CAPITAL LETTER C WITH DOT ABOVE
+       : 0043 0307
+010B   LATIN SMALL LETTER C WITH DOT ABOVE
+       * Maltese, Irish Gaelic (old orthography)
+       : 0063 0307
+010C   LATIN CAPITAL LETTER C WITH CARON
+       : 0043 030C
+010D   LATIN SMALL LETTER C WITH CARON
+       * Czech, Slovak, Slovenian, and many other languages
+       : 0063 030C
+010E   LATIN CAPITAL LETTER D WITH CARON
+       * the form using caron/hacek is preferred in all contexts
+       : 0044 030C
+010F   LATIN SMALL LETTER D WITH CARON
+       * Czech, Slovak
+       * the form using apostrophe is preferred in typesetting
+       : 0064 030C
+0110   LATIN CAPITAL LETTER D WITH STROKE
+       x (latin capital letter eth - 00D0)
+       x (latin small letter d with stroke - 0111)
+       x (latin capital letter african d - 0189)
+0111   LATIN SMALL LETTER D WITH STROKE
+       * Croatian, Vietnamese, Sámi
+       x (latin capital letter d with stroke - 0110)
+       x (cyrillic small letter dje - 0452)
+0112   LATIN CAPITAL LETTER E WITH MACRON
+       : 0045 0304
+0113   LATIN SMALL LETTER E WITH MACRON
+       * Latvian, Latin, ...
+       : 0065 0304
+0114   LATIN CAPITAL LETTER E WITH BREVE
+       : 0045 0306
+0115   LATIN SMALL LETTER E WITH BREVE
+       * Malay, Latin, ...
+       : 0065 0306
+0116   LATIN CAPITAL LETTER E WITH DOT ABOVE
+       : 0045 0307
+0117   LATIN SMALL LETTER E WITH DOT ABOVE
+       * Lithuanian
+       : 0065 0307
+0118   LATIN CAPITAL LETTER E WITH OGONEK
+       : 0045 0328
+0119   LATIN SMALL LETTER E WITH OGONEK
+       * Polish, Lithuanian, ...
+       : 0065 0328
+011A   LATIN CAPITAL LETTER E WITH CARON
+       : 0045 030C
+011B   LATIN SMALL LETTER E WITH CARON
+       * Czech, ...
+       : 0065 030C
+011C   LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+       : 0047 0302
+011D   LATIN SMALL LETTER G WITH CIRCUMFLEX
+       * Esperanto
+       : 0067 0302
+011E   LATIN CAPITAL LETTER G WITH BREVE
+       : 0047 0306
+011F   LATIN SMALL LETTER G WITH BREVE
+       * Turkish, Azerbaijani
+       x (latin small letter g with caron - 01E7)
+       : 0067 0306
+0120   LATIN CAPITAL LETTER G WITH DOT ABOVE
+       : 0047 0307
+0121   LATIN SMALL LETTER G WITH DOT ABOVE
+       * Maltese, Irish Gaelic (old orthography)
+       : 0067 0307
+0122   LATIN CAPITAL LETTER G WITH CEDILLA
+       : 0047 0327
+0123   LATIN SMALL LETTER G WITH CEDILLA
+       * Latvian
+       * there are three major glyph variants
+       : 0067 0327
+0124   LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+       : 0048 0302
+0125   LATIN SMALL LETTER H WITH CIRCUMFLEX
+       * Esperanto
+       : 0068 0302
+0126   LATIN CAPITAL LETTER H WITH STROKE
+0127   LATIN SMALL LETTER H WITH STROKE
+       * Maltese, IPA, ...
+       x (cyrillic small letter tshe - 045B)
+       x (planck constant over two pi - 210F)
+0128   LATIN CAPITAL LETTER I WITH TILDE
+       : 0049 0303
+0129   LATIN SMALL LETTER I WITH TILDE
+       * Greenlandic (old orthography)
+       : 0069 0303
+012A   LATIN CAPITAL LETTER I WITH MACRON
+       : 0049 0304
+012B   LATIN SMALL LETTER I WITH MACRON
+       * Latvian, Latin, ...
+       : 0069 0304
+012C   LATIN CAPITAL LETTER I WITH BREVE
+       : 0049 0306
+012D   LATIN SMALL LETTER I WITH BREVE
+       * Latin, ...
+       : 0069 0306
+012E   LATIN CAPITAL LETTER I WITH OGONEK
+       : 0049 0328
+012F   LATIN SMALL LETTER I WITH OGONEK
+       * Lithuanian, ...
+       : 0069 0328
+0130   LATIN CAPITAL LETTER I WITH DOT ABOVE
+       = LATIN CAPITAL LETTER I DOT
+       * Turkish, Azerbaijani
+       * lowercase is 0069
+       x (latin capital letter i - 0049)
+       : 0049 0307
+0131   LATIN SMALL LETTER DOTLESS I
+       * Turkish, Azerbaijani
+       * uppercase is 0049
+       x (latin small letter i - 0069)
+0132   LATIN CAPITAL LIGATURE IJ
+       # 0049 004A
+0133   LATIN SMALL LIGATURE IJ
+       * Dutch
+       # 0069 006A
+0134   LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+       : 004A 0302
+0135   LATIN SMALL LETTER J WITH CIRCUMFLEX
+       * Esperanto
+       : 006A 0302
+0136   LATIN CAPITAL LETTER K WITH CEDILLA
+       : 004B 0327
+0137   LATIN SMALL LETTER K WITH CEDILLA
+       * Latvian
+       : 006B 0327
+0138   LATIN SMALL LETTER KRA (Greenlandic)
+       * Greenlandic (old orthography)
+0139   LATIN CAPITAL LETTER L WITH ACUTE
+       : 004C 0301
+013A   LATIN SMALL LETTER L WITH ACUTE
+       * Slovak
+       : 006C 0301
+013B   LATIN CAPITAL LETTER L WITH CEDILLA
+       : 004C 0327
+013C   LATIN SMALL LETTER L WITH CEDILLA
+       * Latvian
+       : 006C 0327
+013D   LATIN CAPITAL LETTER L WITH CARON
+       : 004C 030C
+013E   LATIN SMALL LETTER L WITH CARON
+       * Slovak
+       * the form using apostrophe is preferred in typesetting
+       : 006C 030C
+013F   LATIN CAPITAL LETTER L WITH MIDDLE DOT
+       * some fonts show the middle dot inside the L, but the preferred form has the dot following the L
+       # 004C 00B7
+0140   LATIN SMALL LETTER L WITH MIDDLE DOT
+       * Catalan
+       # 006C 00B7
+0141   LATIN CAPITAL LETTER L WITH STROKE
+0142   LATIN SMALL LETTER L WITH STROKE
+       * Polish, ...
+       x (latin small letter l with bar - 019A)
+0143   LATIN CAPITAL LETTER N WITH ACUTE
+       : 004E 0301
+0144   LATIN SMALL LETTER N WITH ACUTE
+       * Polish, ...
+       : 006E 0301
+0145   LATIN CAPITAL LETTER N WITH CEDILLA
+       : 004E 0327
+0146   LATIN SMALL LETTER N WITH CEDILLA
+       * Latvian
+       : 006E 0327
+0147   LATIN CAPITAL LETTER N WITH CARON
+       : 004E 030C
+0148   LATIN SMALL LETTER N WITH CARON
+       * Czech, Slovak
+       : 006E 030C
+0149   LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+       = LATIN SMALL LETTER APOSTROPHE N
+       * Afrikaans
+       * this is not actually a single letter
+       # 02BC 006E
+014A   LATIN CAPITAL LETTER ENG (Sami)
+       * glyph may also have appearance of large form of the small letter
+014B   LATIN SMALL LETTER ENG (Sami)
+       * Sámi, Mende, IPA, ...
+014C   LATIN CAPITAL LETTER O WITH MACRON
+       : 004F 0304
+014D   LATIN SMALL LETTER O WITH MACRON
+       * Latvian, Latin, ...
+       : 006F 0304
+014E   LATIN CAPITAL LETTER O WITH BREVE
+       : 004F 0306
+014F   LATIN SMALL LETTER O WITH BREVE
+       * Latin
+       : 006F 0306
+0150   LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+       : 004F 030B
+0151   LATIN SMALL LETTER O WITH DOUBLE ACUTE
+       * Hungarian
+       : 006F 030B
+0152   LATIN CAPITAL LIGATURE OE
+0153   LATIN SMALL LIGATURE OE
+       = LATIN SMALL LETTER O E
+       = ethel (from Old English eðel)
+       * French, IPA, Old Icelandic, Old English, ...
+       x (latin small letter ae - 00E6)
+       x (latin letter small capital oe - 0276)
+0154   LATIN CAPITAL LETTER R WITH ACUTE
+       : 0052 0301
+0155   LATIN SMALL LETTER R WITH ACUTE
+       * Slovak, ...
+       : 0072 0301
+0156   LATIN CAPITAL LETTER R WITH CEDILLA
+       : 0052 0327
+0157   LATIN SMALL LETTER R WITH CEDILLA
+       * Latvian
+       : 0072 0327
+0158   LATIN CAPITAL LETTER R WITH CARON
+       : 0052 030C
+0159   LATIN SMALL LETTER R WITH CARON
+       * Czech, ...
+       : 0072 030C
+015A   LATIN CAPITAL LETTER S WITH ACUTE
+       : 0053 0301
+015B   LATIN SMALL LETTER S WITH ACUTE
+       * Polish, Indic transliteration, ...
+       : 0073 0301
+015C   LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+       : 0053 0302
+015D   LATIN SMALL LETTER S WITH CIRCUMFLEX
+       * Esperanto
+       : 0073 0302
+015E   LATIN CAPITAL LETTER S WITH CEDILLA *
+       : 0053 0327
+015F   LATIN SMALL LETTER S WITH CEDILLA *
+       * Turkish, Azerbaijani, Romanian, ...
+       * this character is used in both Turkish and Romanian data
+       * a glyph variant with comma below is preferred for Romanian
+       x (latin small letter s with comma below - 0219)
+       : 0073 0327
+0160   LATIN CAPITAL LETTER S WITH CARON
+       : 0053 030C
+0161   LATIN SMALL LETTER S WITH CARON
+       * Czech, Estonian, Finnish, Slovak, and many other languages
+       : 0073 030C
+0162   LATIN CAPITAL LETTER T WITH CEDILLA *
+       : 0054 0327
+0163   LATIN SMALL LETTER T WITH CEDILLA *
+       * Romanian, Semitic transliteration, ...
+       * this character is used in Romanian data
+       * a glyph variant with comma below is preferred for Romanian
+       x (latin small letter t with comma below - 021B)
+       : 0074 0327
+0164   LATIN CAPITAL LETTER T WITH CARON
+       * the form using caron/hacek is preferred in all contexts
+       : 0054 030C
+0165   LATIN SMALL LETTER T WITH CARON
+       * Czech, Slovak
+       * the form using apostrophe is preferred in typesetting
+       : 0074 030C
+0166   LATIN CAPITAL LETTER T WITH STROKE
+0167   LATIN SMALL LETTER T WITH STROKE
+       * Sámi
+0168   LATIN CAPITAL LETTER U WITH TILDE
+       : 0055 0303
+0169   LATIN SMALL LETTER U WITH TILDE
+       * Greenlandic (old orthography)
+       : 0075 0303
+016A   LATIN CAPITAL LETTER U WITH MACRON
+       : 0055 0304
+016B   LATIN SMALL LETTER U WITH MACRON
+       * Latvian, Lithuanian, Latin, ...
+       : 0075 0304
+016C   LATIN CAPITAL LETTER U WITH BREVE
+       : 0055 0306
+016D   LATIN SMALL LETTER U WITH BREVE
+       * Latin, Esperanto, ...
+       : 0075 0306
+016E   LATIN CAPITAL LETTER U WITH RING ABOVE
+       : 0055 030A
+016F   LATIN SMALL LETTER U WITH RING ABOVE
+       * Czech, ...
+       : 0075 030A
+0170   LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+       : 0055 030B
+0171   LATIN SMALL LETTER U WITH DOUBLE ACUTE
+       * Hungarian
+       : 0075 030B
+0172   LATIN CAPITAL LETTER U WITH OGONEK
+       : 0055 0328
+0173   LATIN SMALL LETTER U WITH OGONEK
+       * Lithuanian
+       : 0075 0328
+0174   LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+       : 0057 0302
+0175   LATIN SMALL LETTER W WITH CIRCUMFLEX
+       * Welsh
+       : 0077 0302
+0176   LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+       : 0059 0302
+0177   LATIN SMALL LETTER Y WITH CIRCUMFLEX
+       * Welsh
+       : 0079 0302
+0178   LATIN CAPITAL LETTER Y WITH DIAERESIS
+       * French, Igbo
+       x (latin small letter y with diaeresis - 00FF)
+       : 0059 0308
+0179   LATIN CAPITAL LETTER Z WITH ACUTE
+       : 005A 0301
+017A   LATIN SMALL LETTER Z WITH ACUTE
+       * Polish, ...
+       : 007A 0301
+017B   LATIN CAPITAL LETTER Z WITH DOT ABOVE
+       : 005A 0307
+017C   LATIN SMALL LETTER Z WITH DOT ABOVE
+       * Polish, ...
+       : 007A 0307
+017D   LATIN CAPITAL LETTER Z WITH CARON
+       : 005A 030C
+017E   LATIN SMALL LETTER Z WITH CARON
+       * Czech, Estonian, Finnish, Slovak, Slovenian, and many other languages
+       : 007A 030C
+017F   LATIN SMALL LETTER LONG S
+       * in common use in Roman types until the 18th century
+       * in current use in Fraktur and Gaelic types
+       # 0073 latin small letter s
+@@     0180    Latin Extended-B        024F
+@              Latin extended-B
+0180   LATIN SMALL LETTER B WITH STROKE
+       * Americanist and Indo-Europeanist usage for phonetic beta
+       * Old Saxon
+       x (greek small letter beta - 03B2)
+       x (blank symbol - 2422)
+0181   LATIN CAPITAL LETTER B WITH HOOK
+       * Zulu, Pan-Nigerian alphabet
+       x (latin small letter b with hook - 0253)
+0182   LATIN CAPITAL LETTER B WITH TOPBAR
+0183   LATIN SMALL LETTER B WITH TOPBAR
+       * Zhuang
+       * former Soviet minority language scripts
+       x (cyrillic capital letter be - 0411)
+0184   LATIN CAPITAL LETTER TONE SIX
+0185   LATIN SMALL LETTER TONE SIX
+       * Zhuang
+       * Zhuang tone three is Cyrillic ze
+       * Zhuang tone four is Cyrillic che
+       x (latin small letter tone two - 01A8)
+       x (latin small letter tone five - 01BD)
+       x (cyrillic small letter ze - 0437)
+       x (cyrillic small letter che - 0447)
+       x (cyrillic small letter soft sign - 044C)
+0186   LATIN CAPITAL LETTER OPEN O
+       * typographically a turned C
+       x (latin small letter open o - 0254)
+0187   LATIN CAPITAL LETTER C WITH HOOK
+0188   LATIN SMALL LETTER C WITH HOOK
+       * African
+0189   LATIN CAPITAL LETTER AFRICAN D *
+       * Ewe
+       x (latin capital letter eth - 00D0)
+       x (latin capital letter d with stroke - 0110)
+       x (latin small letter d with tail - 0256)
+018A   LATIN CAPITAL LETTER D WITH HOOK
+       * Pan-Nigerian alphabet
+       x (latin small letter d with hook - 0257)
+018B   LATIN CAPITAL LETTER D WITH TOPBAR
+018C   LATIN SMALL LETTER D WITH TOPBAR
+       * former-Soviet minority language scripts
+018D   LATIN SMALL LETTER TURNED DELTA
+       * archaic phonetic for labialized dental fricative
+       * recommended spellings 007A 02B7 or 007A 032B
+018E   LATIN CAPITAL LETTER REVERSED E
+       = LATIN CAPITAL LETTER TURNED E
+       * Pan-Nigerian alphabet
+       * lowercase is 01DD
+018F   LATIN CAPITAL LETTER SCHWA
+       * Azerbaijani, ...
+       x (latin small letter schwa - 0259)
+       x (cyrillic capital letter schwa - 04D8)
+0190   LATIN CAPITAL LETTER OPEN E
+       = LATIN CAPITAL LETTER EPSILON
+       * African
+       x (latin small letter open e - 025B)
+       x (euler constant - 2107)
+0191   LATIN CAPITAL LETTER F WITH HOOK
+       * African
+0192   LATIN SMALL LETTER F WITH HOOK
+       = LATIN SMALL LETTER SCRIPT F
+       = Florin currency symbol (Netherlands)
+       = function symbol
+       = abbreviation convention for folder
+0193   LATIN CAPITAL LETTER G WITH HOOK
+       * African
+       x (latin small letter g with hook - 0260)
+0194   LATIN CAPITAL LETTER GAMMA
+       * African
+       x (latin small letter gamma - 0263)
+0195   LATIN SMALL LETTER HV (hwair)
+       * Gothic transliteration
+       * uppercase is 01F6
+0196   LATIN CAPITAL LETTER IOTA
+       * African
+       x (latin small letter iota - 0269)
+0197   LATIN CAPITAL LETTER I WITH STROKE
+       = barred i, i bar
+       * African
+       * ISO 6438 gives lowercase as 026A, not 0268
+       x (latin letter small capital i - 026A)
+0198   LATIN CAPITAL LETTER K WITH HOOK
+0199   LATIN SMALL LETTER K WITH HOOK
+       * Hausa, Pan-Nigerian alphabet
+019A   LATIN SMALL LETTER L WITH BAR
+       = barred l
+       * Americanist phonetic usage for 026C
+       x (latin small letter l with stroke - 0142)
+019B   LATIN SMALL LETTER LAMBDA WITH STROKE
+       = barred lambda, lambda bar
+       * Americanist phonetic usage
+019C   LATIN CAPITAL LETTER TURNED M
+       * Zhuang
+       x (latin small letter turned m - 026F)
+019D   LATIN CAPITAL LETTER N WITH LEFT HOOK
+       * African
+       x (latin small letter n with left hook - 0272)
+019E   LATIN SMALL LETTER N WITH LONG RIGHT LEG
+       * archaic phonetic for Japanese syllabic "n"
+       * recommended spelling 006E 0329
+019F   LATIN CAPITAL LETTER O WITH MIDDLE TILDE *
+       = barred o, o bar
+       * lowercase is 0275
+       * African
+       x (cyrillic capital letter barred o - 04E8)
+01A0   LATIN CAPITAL LETTER O WITH HORN
+       : 004F 031B
+01A1   LATIN SMALL LETTER O WITH HORN
+       * Vietnamese
+       : 006F 031B
+01A2   LATIN CAPITAL LETTER OI (gha)
+01A3   LATIN SMALL LETTER OI (gha)
+       = gha
+       * Pan-Turkic Latin alphabets
+01A4   LATIN CAPITAL LETTER P WITH HOOK
+01A5   LATIN SMALL LETTER P WITH HOOK
+       * African
+01A6   LATIN LETTER YR *
+       * old Norse
+       * from German Standard DIN 31624 and ISO 5246-2
+       * lowercase is 0280
+01A7   LATIN CAPITAL LETTER TONE TWO
+01A8   LATIN SMALL LETTER TONE TWO
+       * Zhuang
+       * typographically a reversed S
+       x (latin small letter tone six - 0185)
+01A9   LATIN CAPITAL LETTER ESH
+       * African
+       x (latin small letter esh - 0283)
+       x (greek capital letter sigma - 03A3)
+01AA   LATIN LETTER REVERSED ESH LOOP
+       * archaic phonetic for labialized palatoalveolar or palatal fricative
+       * Twi
+       * recommended spellings 0283 02B7, 00E7 02B7, 0068 0265, etc.
+01AB   LATIN SMALL LETTER T WITH PALATAL HOOK
+       * archaic phonetic for palatalized alveolar or dental stop
+       * recommended spelling 0074 02B2
+01AC   LATIN CAPITAL LETTER T WITH HOOK
+01AD   LATIN SMALL LETTER T WITH HOOK
+       * African
+01AE   LATIN CAPITAL LETTER T WITH RETROFLEX HOOK
+       * African
+       x (latin small letter t with retroflex hook - 0288)
+01AF   LATIN CAPITAL LETTER U WITH HORN
+       : 0055 031B
+01B0   LATIN SMALL LETTER U WITH HORN
+       * Vietnamese
+       : 0075 031B
+01B1   LATIN CAPITAL LETTER UPSILON
+       * African
+       * typographically based on turned capital Greek omega
+       x (latin small letter upsilon - 028A)
+       x (inverted ohm sign - 2127)
+01B2   LATIN CAPITAL LETTER V WITH HOOK
+       = LATIN CAPITAL LETTER SCRIPT V
+       * African
+       x (latin small letter v with hook - 028B)
+01B3   LATIN CAPITAL LETTER Y WITH HOOK
+01B4   LATIN SMALL LETTER Y WITH HOOK
+       * Bini, Esoko, and other Edo languages in West Africa
+01B5   LATIN CAPITAL LETTER Z WITH STROKE
+01B6   LATIN SMALL LETTER Z WITH STROKE
+       = barred z, z bar
+       * Pan-Turkic Latin orthography
+       * handwritten variant of Latin "z"
+       x (latin small letter z - 007A)
+01B7   LATIN CAPITAL LETTER EZH
+       * African, Skolt Sámi
+       * lowercase is 0292
+       x (latin capital letter yogh - 021C)
+       x (cyrillic capital letter abkhasian dze - 04E0)
+01B8   LATIN CAPITAL LETTER EZH REVERSED
+01B9   LATIN SMALL LETTER EZH REVERSED
+       * archaic phonetic for voiced pharyngeal fricative
+       * sometimes typographically rendered with a turned digit 3
+       * recommended spelling 0295
+       x (latin letter pharyngeal voiced fricative - 0295)
+       x (arabic letter ain - 0639)
+01BA   LATIN SMALL LETTER EZH WITH TAIL
+       * archaic phonetic for labialized voiced palatoalveolar or palatal fricative
+       * Twi
+       * recommended spellings 0292 02B7 or 006A 02B7
+01BB   LATIN LETTER TWO WITH STROKE
+       * archaic phonetic for [dz] affricate
+       * recommended spellings 0292 or 0064 007A
+01BC   LATIN CAPITAL LETTER TONE FIVE
+01BD   LATIN SMALL LETTER TONE FIVE
+       * Zhuang
+       x (latin small letter tone six - 0185)
+01BE   LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE
+       * archaic phonetic for [ts] affricate
+       * recommended spelling 0074 0073
+       * letter form is actually derived from ligation of ts, rather than inverted glottal stop
+01BF   LATIN LETTER WYNN
+       = wen
+       * Runic letter borrowed into Latin script
+       * replaced by "w" in modern transcriptions of Old English
+       * uppercase is 01F7
+       x (runic letter wunjo wynn w - 16B9)
+01C0   LATIN LETTER DENTAL CLICK
+       = pipe
+       * Khoisan tradition
+       * "c" in Zulu orthography
+       x (solidus - 002F)
+       x (vertical line - 007C)
+       x (latin small letter turned t - 0287)
+       x (divides - 2223)
+01C1   LATIN LETTER LATERAL CLICK
+       = double pipe
+       * Khoisan tradition
+       * "x" in Zulu orthography
+       x (latin letter inverted glottal stop - 0296)
+       x (parallel to - 2225)
+01C2   LATIN LETTER ALVEOLAR CLICK
+       = double-barred pipe
+       * Khoisan tradition
+       x (not equal to - 2260)
+01C3   LATIN LETTER RETROFLEX CLICK
+       = LATIN LETTER EXCLAMATION MARK
+       * Khoisan tradition
+       * "q" in Zulu orthography
+       x (exclamation mark - 0021)
+       x (latin letter stretched c - 0297)
+@              Croatian digraphs matching Serbian Cyrillic letters
+01C4   LATIN CAPITAL LETTER DZ WITH CARON
+       # 0044 017D
+01C5   LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON
+       # 0044 017E
+01C6   LATIN SMALL LETTER DZ WITH CARON
+       x (cyrillic small letter dzhe - 045F)
+       # 0064 017E
+01C7   LATIN CAPITAL LETTER LJ
+       # 004C 004A
+01C8   LATIN CAPITAL LETTER L WITH SMALL LETTER J
+       # 004C 006A
+01C9   LATIN SMALL LETTER LJ
+       x (cyrillic small letter lje - 0459)
+       # 006C 006A
+01CA   LATIN CAPITAL LETTER NJ
+       # 004E 004A
+01CB   LATIN CAPITAL LETTER N WITH SMALL LETTER J
+       # 004E 006A
+01CC   LATIN SMALL LETTER NJ
+       x (cyrillic small letter nje - 045A)
+       # 006E 006A
+@              Pinyin diacritic-vowel combinations
+01CD   LATIN CAPITAL LETTER A WITH CARON
+       : 0041 030C
+01CE   LATIN SMALL LETTER A WITH CARON
+       * Pinyin third tone
+       : 0061 030C
+01CF   LATIN CAPITAL LETTER I WITH CARON
+       : 0049 030C
+01D0   LATIN SMALL LETTER I WITH CARON
+       * Pinyin third tone
+       : 0069 030C
+01D1   LATIN CAPITAL LETTER O WITH CARON
+       : 004F 030C
+01D2   LATIN SMALL LETTER O WITH CARON
+       * Pinyin third tone
+       : 006F 030C
+01D3   LATIN CAPITAL LETTER U WITH CARON
+       : 0055 030C
+01D4   LATIN SMALL LETTER U WITH CARON
+       * Pinyin third tone
+       : 0075 030C
+01D5   LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
+       : 00DC 0304
+01D6   LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
+       * Pinyin first tone
+       : 00FC 0304
+01D7   LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
+       : 00DC 0301
+01D8   LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
+       * Pinyin second tone
+       : 00FC 0301
+01D9   LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
+       : 00DC 030C
+01DA   LATIN SMALL LETTER U WITH DIAERESIS AND CARON
+       * Pinyin third tone
+       : 00FC 030C
+01DB   LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
+       : 00DC 0300
+01DC   LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE
+       * Pinyin fourth tone
+       : 00FC 0300
+@              Additions
+01DD   LATIN SMALL LETTER TURNED E
+       * Pan-Nigerian alphabet
+       * all other usages of schwa are 0259
+       * uppercase is 018E
+       x (latin small letter schwa - 0259)
+01DE   LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON
+       : 00C4 0304
+01DF   LATIN SMALL LETTER A WITH DIAERESIS AND MACRON
+       * Livonian, Uralicist usage
+       : 00E4 0304
+01E0   LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON
+       : 0226 0304
+01E1   LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON
+       * Uralicist usage
+       : 0227 0304
+01E2   LATIN CAPITAL LETTER AE WITH MACRON (ash) *
+       : 00C6 0304
+01E3   LATIN SMALL LETTER AE WITH MACRON (ash) *
+       * Old Norse, Old English
+       : 00E6 0304
+01E4   LATIN CAPITAL LETTER G WITH STROKE
+01E5   LATIN SMALL LETTER G WITH STROKE
+       * Skolt Sámi
+01E6   LATIN CAPITAL LETTER G WITH CARON
+       : 0047 030C
+01E7   LATIN SMALL LETTER G WITH CARON
+       * Skolt Sámi
+       x (latin small letter g with breve - 011F)
+       : 0067 030C
+01E8   LATIN CAPITAL LETTER K WITH CARON
+       : 004B 030C
+01E9   LATIN SMALL LETTER K WITH CARON
+       * Skolt Sámi
+       : 006B 030C
+01EA   LATIN CAPITAL LETTER O WITH OGONEK
+       : 004F 0328
+01EB   LATIN SMALL LETTER O WITH OGONEK
+       * Sámi, Iroquoian, Old Icelandic
+       : 006F 0328
+01EC   LATIN CAPITAL LETTER O WITH OGONEK AND MACRON
+       : 01EA 0304
+01ED   LATIN SMALL LETTER O WITH OGONEK AND MACRON
+       * Old Icelandic
+       : 01EB 0304
+01EE   LATIN CAPITAL LETTER EZH WITH CARON
+       : 01B7 030C
+01EF   LATIN SMALL LETTER EZH WITH CARON
+       * Skolt Sámi
+       : 0292 030C
+01F0   LATIN SMALL LETTER J WITH CARON
+       * IPA and many languages
+       : 006A 030C
+01F1   LATIN CAPITAL LETTER DZ
+       # 0044 005A
+01F2   LATIN CAPITAL LETTER D WITH SMALL LETTER Z
+       # 0044 007A
+01F3   LATIN SMALL LETTER DZ
+       # 0064 007A
+01F4   LATIN CAPITAL LETTER G WITH ACUTE
+       : 0047 0301
+01F5   LATIN SMALL LETTER G WITH ACUTE
+       * Macedonian and Serbian transliteration
+       : 0067 0301
+01F6   LATIN CAPITAL LETTER HWAIR
+       * lowercase is 0195
+01F7   LATIN CAPITAL LETTER WYNN
+       = wen
+       * lowercase is 01BF
+01F8   LATIN CAPITAL LETTER N WITH GRAVE
+       : 004E 0300
+01F9   LATIN SMALL LETTER N WITH GRAVE
+       * Pinyin
+       : 006E 0300
+01FA   LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
+       : 00C5 0301
+01FB   LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
+       : 00E5 0301
+01FC   LATIN CAPITAL LETTER AE WITH ACUTE (ash) *
+       : 00C6 0301
+01FD   LATIN SMALL LETTER AE WITH ACUTE (ash) *
+       : 00E6 0301
+01FE   LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
+       : 00D8 0301
+01FF   LATIN SMALL LETTER O WITH STROKE AND ACUTE
+       : 00F8 0301
+@              Additions for Slovenian and Croatian
+0200   LATIN CAPITAL LETTER A WITH DOUBLE GRAVE
+       : 0041 030F
+0201   LATIN SMALL LETTER A WITH DOUBLE GRAVE
+       : 0061 030F
+0202   LATIN CAPITAL LETTER A WITH INVERTED BREVE
+       : 0041 0311
+0203   LATIN SMALL LETTER A WITH INVERTED BREVE
+       : 0061 0311
+0204   LATIN CAPITAL LETTER E WITH DOUBLE GRAVE
+       : 0045 030F
+0205   LATIN SMALL LETTER E WITH DOUBLE GRAVE
+       : 0065 030F
+0206   LATIN CAPITAL LETTER E WITH INVERTED BREVE
+       : 0045 0311
+0207   LATIN SMALL LETTER E WITH INVERTED BREVE
+       : 0065 0311
+0208   LATIN CAPITAL LETTER I WITH DOUBLE GRAVE
+       : 0049 030F
+0209   LATIN SMALL LETTER I WITH DOUBLE GRAVE
+       : 0069 030F
+020A   LATIN CAPITAL LETTER I WITH INVERTED BREVE
+       : 0049 0311
+020B   LATIN SMALL LETTER I WITH INVERTED BREVE
+       : 0069 0311
+020C   LATIN CAPITAL LETTER O WITH DOUBLE GRAVE
+       : 004F 030F
+020D   LATIN SMALL LETTER O WITH DOUBLE GRAVE
+       : 006F 030F
+020E   LATIN CAPITAL LETTER O WITH INVERTED BREVE
+       : 004F 0311
+020F   LATIN SMALL LETTER O WITH INVERTED BREVE
+       : 006F 0311
+0210   LATIN CAPITAL LETTER R WITH DOUBLE GRAVE
+       : 0052 030F
+0211   LATIN SMALL LETTER R WITH DOUBLE GRAVE
+       : 0072 030F
+0212   LATIN CAPITAL LETTER R WITH INVERTED BREVE
+       : 0052 0311
+0213   LATIN SMALL LETTER R WITH INVERTED BREVE
+       : 0072 0311
+0214   LATIN CAPITAL LETTER U WITH DOUBLE GRAVE
+       : 0055 030F
+0215   LATIN SMALL LETTER U WITH DOUBLE GRAVE
+       : 0075 030F
+0216   LATIN CAPITAL LETTER U WITH INVERTED BREVE
+       : 0055 0311
+0217   LATIN SMALL LETTER U WITH INVERTED BREVE
+       : 0075 0311
+@              Additions for Romanian
+0218   LATIN CAPITAL LETTER S WITH COMMA BELOW *
+       : 0053 0326
+0219   LATIN SMALL LETTER S WITH COMMA BELOW *
+       * Romanian, when distinct comma below form is required
+       x (latin small letter s with cedilla - 015F)
+       : 0073 0326
+021A   LATIN CAPITAL LETTER T WITH COMMA BELOW *
+       : 0054 0326
+021B   LATIN SMALL LETTER T WITH COMMA BELOW *
+       * Romanian, when distinct comma below form is required
+       x (latin small letter t with cedilla - 0163)
+       : 0074 0326
+@              Miscellaneous additions
+021C   LATIN CAPITAL LETTER YOGH
+       x (latin capital letter ezh - 01B7)
+021D   LATIN SMALL LETTER YOGH
+       * Middle English, Scots
+       x (latin small letter ezh - 0292)
+       x (ounce sign - 2125)
+021E   LATIN CAPITAL LETTER H WITH CARON
+       : 0048 030C
+021F   LATIN SMALL LETTER H WITH CARON
+       * Finnish Romany
+       : 0068 030C
+0222   LATIN CAPITAL LETTER OU
+0223   LATIN SMALL LETTER OU
+       * Algonquin, Huron
+       x (digit eight - 0038)
+0224   LATIN CAPITAL LETTER Z WITH HOOK
+0225   LATIN SMALL LETTER Z WITH HOOK
+       * Middle High German
+0226   LATIN CAPITAL LETTER A WITH DOT ABOVE
+       : 0041 0307
+0227   LATIN SMALL LETTER A WITH DOT ABOVE
+       * Uralicist usage
+       : 0061 0307
+0228   LATIN CAPITAL LETTER E WITH CEDILLA
+       : 0045 0327
+0229   LATIN SMALL LETTER E WITH CEDILLA
+       : 0065 0327
+@              Additions for Livonian
+022A   LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON
+       : 00D6 0304
+022B   LATIN SMALL LETTER O WITH DIAERESIS AND MACRON
+       * Livonian
+       : 00F6 0304
+022C   LATIN CAPITAL LETTER O WITH TILDE AND MACRON
+       : 00D5 0304
+022D   LATIN SMALL LETTER O WITH TILDE AND MACRON
+       * Livonian
+       : 00F5 0304
+022E   LATIN CAPITAL LETTER O WITH DOT ABOVE
+       : 004F 0307
+022F   LATIN SMALL LETTER O WITH DOT ABOVE
+       * Livonian
+       : 006F 0307
+0230   LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
+       : 022E 0304
+0231   LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON
+       * Livonian
+       : 022F 0304
+0232   LATIN CAPITAL LETTER Y WITH MACRON
+       : 0059 0304
+0233   LATIN SMALL LETTER Y WITH MACRON
+       * Livonian, Cornish
+       : 0079 0304
+@@     0250    IPA Extensions  02AF
+@              IPA extensions
+@+             IPA includes basic Latin letters and a number of Latin letters from other blocks.
+               x (latin small letter ae - 00E6)
+               x (latin small letter c with cedilla - 00E7)
+               x (latin small letter eth - 00F0)
+               x (latin small letter o with stroke - 00F8)
+               x (latin small letter h with stroke - 0127)
+               x (latin small letter eng - 014B)
+               x (latin small ligature oe - 0153)
+               x (greek small letter beta - 03B2)
+               x (greek small letter theta - 03B8)
+               x (greek small letter lamda - 03BB)
+               x (greek small letter chi - 03C7)
+0250   LATIN SMALL LETTER TURNED A
+       * low central unrounded vowel
+0251   LATIN SMALL LETTER ALPHA
+       = LATIN SMALL LETTER SCRIPT A
+       * low back unrounded vowel
+       x (greek small letter alpha - 03B1)
+0252   LATIN SMALL LETTER TURNED ALPHA
+       * low back rounded vowel
+0253   LATIN SMALL LETTER B WITH HOOK
+       * implosive bilabial stop
+       * Pan-Nigerian alphabet
+       x (latin capital letter b with hook - 0181)
+0254   LATIN SMALL LETTER OPEN O
+       * typographically a turned c
+       * lower-mid back rounded vowel
+       x (latin capital letter open o - 0186)
+0255   LATIN SMALL LETTER C WITH CURL
+       * voiceless alveolo-palatal laminal fricative
+       * used in transcription of Mandarin Chinese
+       * sound spelled with 015B in Polish
+0256   LATIN SMALL LETTER D WITH TAIL
+       = LATIN SMALL LETTER D RETROFLEX HOOK
+       * voiced retroflex stop
+       x (latin capital letter african d - 0189)
+0257   LATIN SMALL LETTER D WITH HOOK
+       * implosive dental or alveolar stop
+       * Ewe, Pan-Nigerian alphabet
+       x (latin capital letter d with hook - 018A)
+0258   LATIN SMALL LETTER REVERSED E
+       * upper-mid central unrounded vowel
+0259   LATIN SMALL LETTER SCHWA
+       * mid-central unrounded vowel
+       * variant uppercase form 018E is associated with 01DD
+       x (latin capital letter schwa - 018F)
+       x (latin small letter turned e - 01DD)
+       x (cyrillic small letter schwa - 04D9)
+025A   LATIN SMALL LETTER SCHWA WITH HOOK
+       * rhotacized schwa
+025B   LATIN SMALL LETTER OPEN E
+       = LATIN SMALL LETTER EPSILON
+       * lower-mid front unrounded vowel
+       x (latin capital letter open e - 0190)
+       x (greek small letter epsilon - 03B5)
+025C   LATIN SMALL LETTER REVERSED OPEN E
+       * lower-mid central unrounded vowel
+025D   LATIN SMALL LETTER REVERSED OPEN E WITH HOOK
+       * rhotacized lower-mid central vowel
+025E   LATIN SMALL LETTER CLOSED REVERSED OPEN E
+       = LATIN SMALL LETTER CLOSED REVERSED EPSILON
+       * lower-mid central rounded vowel
+025F   LATIN SMALL LETTER DOTLESS J WITH STROKE
+       * voiced palatal stop
+       * typographically a turned f, but better thought of as a form of j
+       * "gy" in Hungarian orthography
+       * also archaic phonetic for palatoalveolar affricate 02A4
+0260   LATIN SMALL LETTER G WITH HOOK
+       * implosive velar stop
+       x (latin capital letter g with hook - 0193)
+0261   LATIN SMALL LETTER SCRIPT G
+       * voiced velar stop
+       x (latin small letter g - 0067)
+0262   LATIN LETTER SMALL CAPITAL G
+       * voiced uvular stop
+0263   LATIN SMALL LETTER GAMMA
+       * voiced velar fricative
+       x (latin capital letter gamma - 0194)
+       x (greek small letter gamma - 03B3)
+0264   LATIN SMALL LETTER RAMS HORN
+       = LATIN SMALL LETTER BABY GAMMA
+       * upper-mid back unrounded vowel
+0265   LATIN SMALL LETTER TURNED H
+       * voiced rounded palatal approximant
+0266   LATIN SMALL LETTER H WITH HOOK
+       * breathy-voiced glottal fricative
+       x (modifier letter small h with hook - 02B1)
+0267   LATIN SMALL LETTER HENG WITH HOOK
+       * voiceless coarticulated velar and palatoalveolar fricative
+       * "tj" or "kj" or "sj" in some Swedish dialects
+0268   LATIN SMALL LETTER I WITH STROKE
+       = barred i, i bar
+       * high central unrounded vowel
+       * ISO 6438 gives lowercase of 0197 as 026A, not 0268
+0269   LATIN SMALL LETTER IOTA
+       * semi-high front unrounded vowel
+@+             * obsoleted by IPA in 1989
+       * preferred use is 026A LATIN LETTER SMALL CAPITAL I
+       x (latin capital letter iota - 0196)
+       x (greek small letter iota - 03B9)
+026A   LATIN LETTER SMALL CAPITAL I
+       * semi-high front unrounded vowel
+       * preferred IPA alternate for 0269
+       x (latin capital letter i with stroke - 0197)
+026B   LATIN SMALL LETTER L WITH MIDDLE TILDE
+       * velarized voiced alveolar lateral approximant
+026C   LATIN SMALL LETTER L WITH BELT
+       * voiceless alveolar lateral fricative
+026D   LATIN SMALL LETTER L WITH RETROFLEX HOOK
+       * voiced retroflex lateral
+026E   LATIN SMALL LETTER LEZH
+       * voiced lateral fricative
+       * "dhl" in Zulu orthography
+026F   LATIN SMALL LETTER TURNED M
+       * high back unrounded vowel
+       x (latin capital letter turned m - 019C)
+0270   LATIN SMALL LETTER TURNED M WITH LONG LEG
+       * voiced velar approximant
+0271   LATIN SMALL LETTER M WITH HOOK
+       * voiced labiodental nasal
+0272   LATIN SMALL LETTER N WITH LEFT HOOK
+       * voiced palatal nasal
+       x (latin capital letter n with left hook - 019D)
+0273   LATIN SMALL LETTER N WITH RETROFLEX HOOK
+       * voiced retroflex nasal
+0274   LATIN LETTER SMALL CAPITAL N
+       * voiced uvular nasal
+0275   LATIN SMALL LETTER BARRED O
+       = o bar
+       * rounded mid-central vowel, i.e. rounded schwa
+       * uppercase is 019F
+       x (greek small letter theta - 03B8)
+       x (cyrillic small letter fita - 0473)
+       x (cyrillic small letter barred o - 04E9)
+0276   LATIN LETTER SMALL CAPITAL OE
+       * low front rounded vowel
+       x (latin small ligature oe - 0153)
+0277   LATIN SMALL LETTER CLOSED OMEGA
+       * semi-high back rounded vowel
+@+             * obsoleted by IPA in 1989
+       * preferred use is 028A latin small letter upsilon
+0278   LATIN SMALL LETTER PHI
+       * voiceless bilabial fricative
+       x (greek small letter phi - 03C6)
+0279   LATIN SMALL LETTER TURNED R
+       * voiced alveolar approximant
+       x (modifier letter small turned r - 02B4)
+027A   LATIN SMALL LETTER TURNED R WITH LONG LEG
+       * voiced lateral flap
+027B   LATIN SMALL LETTER TURNED R WITH HOOK
+       * voiced retroflex approximant
+       x (modifier letter small turned r with hook - 02B5)
+027C   LATIN SMALL LETTER R WITH LONG LEG
+       * voiced strident apico-alveolar trill
+@+             * obsoleted by IPA in 1989
+       * sound spelled with 0159 in Czech
+       * preferred phonetic representation for Czech is 0072 031D
+       * in current use in Gaelic types (as glyph variant of 0072)
+027D   LATIN SMALL LETTER R WITH TAIL
+       * voiced retroflex flap
+027E   LATIN SMALL LETTER R WITH FISHHOOK
+       * voiced alveolar flap or tap
+027F   LATIN SMALL LETTER REVERSED R WITH FISHHOOK
+       * apical dental vowel
+       * used in Sinological tradition
+       * IPA spelling - 007A 0329
+0280   LATIN LETTER SMALL CAPITAL R *
+       * voiced uvular trill
+       * Germanic, Old Norse
+       * uppercase is 01A6
+0281   LATIN LETTER SMALL CAPITAL INVERTED R
+       * voiced uvular fricative or approximant
+       x (modifier letter small capital inverted r - 02B6)
+0282   LATIN SMALL LETTER S WITH HOOK
+       * voiceless retroflex fricative
+0283   LATIN SMALL LETTER ESH
+       * voiceless postalveolar fricative
+       x (latin capital letter esh - 01A9)
+       x (integral - 222B)
+0284   LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK
+       * implosive palatal stop
+       * typographically based on 025F, not on 0283
+0285   LATIN SMALL LETTER SQUAT REVERSED ESH
+       * apical retroflex vowel
+       * used in Sinological tradition
+       * IPA spelling - 0290 0329
+0286   LATIN SMALL LETTER ESH WITH CURL
+       * palatalized voiceless postalveolar fricative
+       * suggested spelling - 0283 02B2
+0287   LATIN SMALL LETTER TURNED T
+       * dental click (sound of "tsk tsk")
+       x (latin letter dental click - 01C0)
+0288   LATIN SMALL LETTER T WITH RETROFLEX HOOK
+       * voiceless retroflex stop
+       x (latin capital letter t with retroflex hook - 01AE)
+0289   LATIN SMALL LETTER U BAR
+       * high central rounded vowel
+028A   LATIN SMALL LETTER UPSILON
+       * semi-high back rounded vowel
+       * preferred IPA alternate to 0277
+       x (latin capital letter upsilon - 01B1)
+       x (greek small letter upsilon - 03C5)
+028B   LATIN SMALL LETTER V WITH HOOK
+       = LATIN SMALL LETTER SCRIPT V
+       * voiced labiodental approximant
+       x (latin capital letter v with hook - 01B2)
+       x (greek small letter upsilon - 03C5)
+028C   LATIN SMALL LETTER TURNED V
+       = caret, wedge
+       * lower-mid back unrounded vowel
+       x (greek capital letter lamda - 039B)
+       x (caret - 2038)
+       x (logical and - 2227)
+028D   LATIN SMALL LETTER TURNED W
+       * voiceless rounded labiovelar approximant
+028E   LATIN SMALL LETTER TURNED Y
+       * voiced lateral approximant
+028F   LATIN LETTER SMALL CAPITAL Y
+       * semi-high front rounded vowel
+0290   LATIN SMALL LETTER Z WITH RETROFLEX HOOK
+       * voiced retroflex fricative
+0291   LATIN SMALL LETTER Z WITH CURL
+       * voiced alveolo-palatal laminal fricative
+       * sound spelled with 017A in Polish
+0292   LATIN SMALL LETTER EZH
+       = LATIN SMALL LETTER YOGH
+       = dram
+       * voiced postalveolar fricative
+       * uppercase is 01B7
+       * Skolt Sámi
+       x (latin small letter yogh - 021D)
+       x (cyrillic small letter abkhasian dze - 04E1)
+       x (ounce sign - 2125)
+0293   LATIN SMALL LETTER EZH WITH CURL
+       * palatalized voiced postalveolar fricative
+0294   LATIN LETTER GLOTTAL STOP
+       x (modifier letter glottal stop - 02C0)
+0295   LATIN LETTER PHARYNGEAL VOICED FRICATIVE
+       = LATIN LETTER REVERSED GLOTTAL STOP
+       * voiced pharyngeal fricative
+       * ain
+       x (latin small letter ezh reversed - 01B9)
+       x (modifier letter reversed glottal stop - 02C1)
+0296   LATIN LETTER INVERTED GLOTTAL STOP
+       * lateral click
+       x (latin letter lateral click - 01C1)
+0297   LATIN LETTER STRETCHED C
+       * palatal (or alveolar) click
+       x (latin letter retroflex click - 01C3)
+       x (complement - 2201)
+0298   LATIN LETTER BILABIAL CLICK
+       = LATIN LETTER BULLSEYE
+       x (circled dot operator - 2299)
+0299   LATIN LETTER SMALL CAPITAL B
+       * bilabial trill
+029A   LATIN SMALL LETTER CLOSED OPEN E
+       = LATIN SMALL LETTER CLOSED EPSILON
+       * lower-mid front rounded vowel
+       * non-IPA alternate for the preferred 0153
+029B   LATIN LETTER SMALL CAPITAL G WITH HOOK
+       * voiced uvular implosive
+029C   LATIN LETTER SMALL CAPITAL H
+       * voiceless epiglottal fricative
+029D   LATIN SMALL LETTER J WITH CROSSED-TAIL
+       * voiced palatal fricative
+029E   LATIN SMALL LETTER TURNED K
+       * proposed for velar click
+@+             * withdrawn by IPA in 1970
+029F   LATIN LETTER SMALL CAPITAL L
+       * velar lateral approximant
+02A0   LATIN SMALL LETTER Q WITH HOOK
+       * voiceless uvular implosive
+02A1   LATIN LETTER GLOTTAL STOP WITH STROKE
+       * voiced epiglottal stop
+02A2   LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE
+       * voiced epiglottal fricative
+02A3   LATIN SMALL LETTER DZ DIGRAPH
+       * voiced dental affricate
+02A4   LATIN SMALL LETTER DEZH DIGRAPH
+       * voiced postalveolar affricate
+02A5   LATIN SMALL LETTER DZ DIGRAPH WITH CURL
+       * voiced alveolo-palatal affricate
+02A6   LATIN SMALL LETTER TS DIGRAPH
+       * voiceless dental affricate
+02A7   LATIN SMALL LETTER TESH DIGRAPH
+       * voiceless postalveolar affricate
+02A8   LATIN SMALL LETTER TC DIGRAPH WITH CURL
+       * voiceless alveolo-palatal affricate
+@              IPA characters for disordered speech
+02A9   LATIN SMALL LETTER FENG DIGRAPH
+       * velopharyngeal fricative
+02AA   LATIN SMALL LETTER LS DIGRAPH
+       * lateral alveolar fricative (lisp)
+02AB   LATIN SMALL LETTER LZ DIGRAPH
+       * voiced lateral alveolar fricative
+02AC   LATIN LETTER BILABIAL PERCUSSIVE
+       * audible lip smack
+02AD   LATIN LETTER BIDENTAL PERCUSSIVE
+       * audible teeth gnashing
+@@     02B0    Spacing Modifier Letters        02FF
+@              Phonetic modifiers derived from Latin letters
+02B0   MODIFIER LETTER SMALL H
+       * aspiration
+       # <super> 0068
+02B1   MODIFIER LETTER SMALL H WITH HOOK
+       * breathy voiced, murmured
+       x (latin small letter h with hook - 0266)
+       x (combining diaeresis below - 0324)
+       # <super> 0266
+02B2   MODIFIER LETTER SMALL J
+       * palatalization
+       x (combining palatalized hook below - 0321)
+       # <super> 006A
+02B3   MODIFIER LETTER SMALL R
+       # <super> 0072
+02B4   MODIFIER LETTER SMALL TURNED R
+       x (latin small letter turned r - 0279)
+       # <super> 0279
+02B5   MODIFIER LETTER SMALL TURNED R WITH HOOK
+       x (latin small letter turned r with hook - 027B)
+       # <super> 027B
+02B6   MODIFIER LETTER SMALL CAPITAL INVERTED R
+       * preceding four used for r-coloring or r-offglides
+       x (latin letter small capital inverted r - 0281)
+       # <super> 0281
+02B7   MODIFIER LETTER SMALL W
+       * labialization
+       x (combining inverted double arch below - 032B)
+       # <super> 0077
+02B8   MODIFIER LETTER SMALL Y
+       * palatalization
+       * common Americanist substitution for 02B2
+       # <super> 0079
+@              Miscellaneous phonetic modifiers
+02B9   MODIFIER LETTER PRIME
+       * primary stress, emphasis
+       * transliteration of mjagkij znak (Cyrillic soft sign: palatalization)
+       x (apostrophe - 0027)
+       x (acute accent - 00B4)
+       x (modifier letter acute accent - 02CA)
+       x (combining acute accent - 0301)
+       x (greek numeral sign - 0374)
+       x (prime - 2032)
+02BA   MODIFIER LETTER DOUBLE PRIME
+       * exaggerated stress, contrastive stress
+       * transliteration of tverdyj znak (Cyrillic hard sign: no palatalization)
+       x (quotation mark - 0022)
+       x (combining double acute accent - 030B)
+       x (double prime - 2033)
+02BB   MODIFIER LETTER TURNED COMMA
+       * typographical alternate for 02BD or 02BF
+       x (combining turned comma above - 0312)
+       x (left single quotation mark - 2018)
+02BC   MODIFIER LETTER APOSTROPHE
+       = apostrophe
+       * glottal stop, glottalization, ejective
+       * spacing clone of Greek smooth breathing mark
+       * many languages use this as a letter of their alphabets
+       x (apostrophe - 0027)
+       x (combining comma above - 0313)
+       x (combining comma above right - 0315)
+       x (armenian apostrophe - 055A)
+       x (right single quotation mark - 2019)
+02BD   MODIFIER LETTER REVERSED COMMA
+       * weak aspiration
+       * spacing clone of Greek rough breathing mark
+       x (combining reversed comma above - 0314)
+       x (armenian modifier letter left half ring - 0559)
+       x (single high-reversed-9 quotation mark - 201B)
+02BE   MODIFIER LETTER RIGHT HALF RING
+       * transliteration of Arabic hamza (glottal stop)
+       x (armenian apostrophe - 055A)
+       x (arabic letter hamza - 0621)
+02BF   MODIFIER LETTER LEFT HALF RING
+       * transliteration of Arabic ain (voiced pharyngeal fricative)
+       x (armenian modifier letter left half ring - 0559)
+       x (arabic letter ain - 0639)
+02C0   MODIFIER LETTER GLOTTAL STOP
+       * ejective or glottalized
+       * typographical alternate for 02BC or 02BE
+       x (latin letter glottal stop - 0294)
+       x (combining hook above - 0309)
+02C1   MODIFIER LETTER REVERSED GLOTTAL STOP
+       * typographical alternate for 02BF
+       x (latin letter pharyngeal voiced fricative - 0295)
+02C2   MODIFIER LETTER LEFT ARROWHEAD
+       * fronted articulation
+02C3   MODIFIER LETTER RIGHT ARROWHEAD
+       * backed articulation
+02C4   MODIFIER LETTER UP ARROWHEAD
+       * raised articulation
+       x (circumflex accent - 005E)
+       x (up arrowhead - 2303)
+02C5   MODIFIER LETTER DOWN ARROWHEAD
+       * lowered articulation
+02C6   MODIFIER LETTER CIRCUMFLEX ACCENT
+       * rising-falling tone, falling tone, secondary stress, etc.
+       x (circumflex accent - 005E)
+       x (combining circumflex accent - 0302)
+02C7   CARON (Mandarin Chinese third tone)
+       = hacek
+       * falling-rising tone
+       * Mandarin Chinese third tone
+       x (combining caron - 030C)
+02C8   MODIFIER LETTER VERTICAL LINE
+       * primary stress, downstep
+       * precedes letter or syllable modified
+       x (apostrophe - 0027)
+       x (combining vertical line above - 030D)
+02C9   MODIFIER LETTER MACRON (Mandarin Chinese first tone)
+       * high level tone
+       * precedes or follows letter or syllable modified
+       * Mandarin Chinese first tone
+       x (macron - 00AF)
+       x (combining macron - 0304)
+02CA   MODIFIER LETTER ACUTE ACCENT (Mandarin Chinese second tone)
+       * high-rising tone (IPA), high tone, primary stress
+       * Mandarin Chinese second tone
+       x (acute accent - 00B4)
+       x (modifier letter prime - 02B9)
+       x (combining acute accent - 0301)
+       x (greek numeral sign - 0374)
+       x (armenian emphasis mark - 055B)
+02CB   MODIFIER LETTER GRAVE ACCENT (Mandarin Chinese fourth tone)
+       * high-falling tone (IPA), low tone, secondary or tertiary stress
+       * Mandarin Chinese fourth tone
+       x (grave accent - 0060)
+       x (combining grave accent - 0300)
+       x (armenian comma - 055D)
+02CC   MODIFIER LETTER LOW VERTICAL LINE
+       * secondary stress
+       * precedes letter or syllable modified
+       x (combining vertical line below - 0329)
+02CD   MODIFIER LETTER LOW MACRON
+       * low level tone
+       x (low line - 005F)
+       x (combining macron below - 0331)
+02CE   MODIFIER LETTER LOW GRAVE ACCENT
+       * low-falling tone
+02CF   MODIFIER LETTER LOW ACUTE ACCENT
+       * low-rising tone
+       x (greek lower numeral sign - 0375)
+02D0   MODIFIER LETTER TRIANGULAR COLON
+       * length mark
+       x (colon - 003A)
+02D1   MODIFIER LETTER HALF TRIANGULAR COLON
+       * half-length mark
+       x (middle dot - 00B7)
+02D2   MODIFIER LETTER CENTRED RIGHT HALF RING
+       * more rounded articulation
+02D3   MODIFIER LETTER CENTRED LEFT HALF RING
+       * less rounded articulation
+02D4   MODIFIER LETTER UP TACK
+       * vowel raising or closing
+       x (combining up tack below - 031D)
+       x (combining dot below - 0323)
+02D5   MODIFIER LETTER DOWN TACK
+       * vowel lowering or opening
+       x (combining left half ring below - 031C)
+       x (combining down tack below - 031E)
+02D6   MODIFIER LETTER PLUS SIGN
+       * advanced or fronted articulation
+       x (combining plus sign below - 031F)
+02D7   MODIFIER LETTER MINUS SIGN
+       * retracted or backed articulation
+       * glyph may have small end-serifs
+       x (combining minus sign below - 0320)
+@              Spacing clones of diacritics
+02D8   BREVE
+       x (combining breve - 0306)
+       # 0020 0306
+02D9   DOT ABOVE (Mandarin Chinese light tone)
+       * Mandarin Chinese fifth tone (light or neutral)
+       x (combining dot above - 0307)
+       # 0020 0307
+02DA   RING ABOVE
+       x (degree sign - 00B0)
+       x (combining ring above - 030A)
+       # 0020 030A
+02DB   OGONEK
+       x (combining ogonek - 0328)
+       # 0020 0328
+02DC   SMALL TILDE
+       x (tilde - 007E)
+       x (combining tilde - 0303)
+       x (tilde operator - 223C)
+       # 0020 0303
+02DD   DOUBLE ACUTE ACCENT
+       x (combining double acute accent - 030B)
+       # 0020 030B
+@              Additions based on 1989 IPA
+02DE   MODIFIER LETTER RHOTIC HOOK
+       * rhotacization in vowel
+       * often ligated: 025A = 0259 + 02DE; 025D = 025C + 02DE
+02DF   MODIFIER LETTER CROSS ACCENT
+       * Swedish grave accent
+02E0   MODIFIER LETTER SMALL GAMMA
+       * these modifier letters are occasionally used in transcription of affricates
+       # <super> 0263
+02E1   MODIFIER LETTER SMALL L
+       # <super> 006C
+02E2   MODIFIER LETTER SMALL S
+       # <super> 0073
+02E3   MODIFIER LETTER SMALL X
+       # <super> 0078
+02E4   MODIFIER LETTER SMALL REVERSED GLOTTAL STOP
+       # <super> 0295
+@              Tone letters
+02E5   MODIFIER LETTER EXTRA-HIGH TONE BAR
+02E6   MODIFIER LETTER HIGH TONE BAR
+02E7   MODIFIER LETTER MID TONE BAR
+02E8   MODIFIER LETTER LOW TONE BAR
+02E9   MODIFIER LETTER EXTRA-LOW TONE BAR
+02EA   MODIFIER LETTER YIN DEPARTING TONE MARK
+02EB   MODIFIER LETTER YANG DEPARTING TONE MARK
+@              IPA modifiers
+02EC   MODIFIER LETTER VOICING
+02ED   MODIFIER LETTER UNASPIRATED
+@              Other modifier letters
+02EE   MODIFIER LETTER DOUBLE APOSTROPHE
+
+2000   EN QUAD
+       : 2002 en space
+2001   EM QUAD
+       = mutton quad
+       : 2003 em space
+2002   EN SPACE
+       = nut
+       * half an em
+       # 0020 space
+2003   EM SPACE
+       = mutton
+       * nominally, a space equal to the type size in points
+       * may scale by the condensation factor of a font
+       # 0020 space
+2004   THREE-PER-EM SPACE
+       = thick space
+       # 0020 space
+2005   FOUR-PER-EM SPACE
+       = mid space
+       # 0020 space
+2006   SIX-PER-EM SPACE
+       * in computer typography sometimes equated to thin space
+       # 0020 space
+2007   FIGURE SPACE
+       * space equal to tabular width of a font
+       * this is equivalent to the digit width of fonts with fixed-width digits
+       # <noBreak> 0020
+2008   PUNCTUATION SPACE
+       * space equal to narrow punctuation of a font
+       # 0020 space
+2009   THIN SPACE
+       * a fifth of an em (or sometimes a sixth)
+       # 0020 space
+200A   HAIR SPACE
+       * thinner than a thin space
+       * in traditional typography, the thinnest space available
+       # 0020 space
+200B   ZERO WIDTH SPACE
+       * nominally zero width, but may expand in justification
+@              Formatting characters
+200C   ZERO WIDTH NON-JOINER
+       = ZWNJ
+200D   ZERO WIDTH JOINER
+       = ZWJ
+200E   LEFT-TO-RIGHT MARK
+       = LRM
+200F   RIGHT-TO-LEFT MARK
+       = RLM
+@              Dashes
+2010   HYPHEN
+       x (hyphen-minus - 002D)
+2011   NON-BREAKING HYPHEN
+       x (hyphen-minus - 002D)
+       # <noBreak> 2010
+2012   FIGURE DASH
+2013   EN DASH
+2014   EM DASH
+       * may be used in pairs to offset parenthetical text
+       x (katakana-hiragana prolonged sound mark - 30FC)
+2015   HORIZONTAL BAR
+       = QUOTATION DASH
+       * long dash introducing quoted text
+@              General punctuation
+2016   DOUBLE VERTICAL LINE
+       * used in pairs to indicate norm of a matrix
+       x (parallel to - 2225)
+2017   DOUBLE LOW LINE
+       * this is a spacing character
+       x (low line - 005F)
+       x (combining double low line - 0333)
+       # 0020 0333
+2018   LEFT SINGLE QUOTATION MARK
+       = SINGLE TURNED COMMA QUOTATION MARK
+       * this is the preferred glyph (as opposed to 201B)
+       x (apostrophe - 0027)
+       x (modifier letter turned comma - 02BB)
+       x (heavy single turned comma quotation mark ornament - 275B)
+2019   RIGHT SINGLE QUOTATION MARK
+       = SINGLE COMMA QUOTATION MARK
+       * this is the preferred character to use for apostrophe
+       x (apostrophe - 0027)
+       x (modifier letter apostrophe - 02BC)
+       x (heavy single comma quotation mark ornament - 275C)
+201A   SINGLE LOW-9 QUOTATION MARK
+       = LOW SINGLE COMMA QUOTATION MARK
+       * used as opening single quotation mark in some languages
+201B   SINGLE HIGH-REVERSED-9 QUOTATION MARK
+       = SINGLE REVERSED COMMA QUOTATION MARK
+       * glyph variant of 2018
+       x (modifier letter reversed comma - 02BD)
+201C   LEFT DOUBLE QUOTATION MARK
+       = DOUBLE TURNED COMMA QUOTATION MARK
+       * this is the preferred glyph (as opposed to 201F)
+       x (quotation mark - 0022)
+       x (heavy double turned comma quotation mark ornament - 275D)
+       x (reversed double prime quotation mark - 301D)
+201D   RIGHT DOUBLE QUOTATION MARK
+       = DOUBLE COMMA QUOTATION MARK
+       x (quotation mark - 0022)
+       x (double prime - 2033)
+       x (heavy double comma quotation mark ornament - 275E)
+       x (double prime quotation mark - 301E)
+201E   DOUBLE LOW-9 QUOTATION MARK
+       = LOW DOUBLE COMMA QUOTATION MARK
+       * used as opening double quotation mark in some languages
+       x (low double prime quotation mark - 301F)
+201F   DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+       = DOUBLE REVERSED COMMA QUOTATION MARK
+       * glyph variant of 201C
+2020   DAGGER
+       = obelisk, obelus, long cross
+2021   DOUBLE DAGGER
+       = diesis, double obelisk
+2022   BULLET
+       = black small circle
+       x (middle dot - 00B7)
+       x (one dot leader - 2024)
+       x (bullet operator - 2219)
+       x (inverse bullet - 25D8)
+       x (white bullet - 25E6)
+2023   TRIANGULAR BULLET
+       x (end of proof - 220E)
+       x (black right-pointing small triangle - 25B8)
+2024   ONE DOT LEADER
+       x (middle dot - 00B7)
+       x (bullet - 2022)
+       x (bullet operator - 2219)
+       # 002E full stop
+2025   TWO DOT LEADER
+       # 002E 002E
+2026   HORIZONTAL ELLIPSIS
+       = three dot leader
+       x (vertical ellipsis - 22EE)
+       # 002E 002E 002E
+2027   HYPHENATION POINT
+@              Formatting characters
+2028   LINE SEPARATOR
+       * may be used to represent this semantic unambiguously
+2029   PARAGRAPH SEPARATOR
+       * may be used to represent this semantic unambiguously
+202A   LEFT-TO-RIGHT EMBEDDING
+       = LRE
+202B   RIGHT-TO-LEFT EMBEDDING
+       = RLE
+202C   POP DIRECTIONAL FORMATTING
+       = PDF
+202D   LEFT-TO-RIGHT OVERRIDE
+       = LRO
+202E   RIGHT-TO-LEFT OVERRIDE
+       = RLO
+202F   NARROW NO-BREAK SPACE
+       x (no-break space - 00A0)
+       # <noBreak> 0020
+@              General punctuation
+2030   PER MILLE SIGN
+       x (percent sign - 0025)
+2031   PER TEN THOUSAND SIGN
+       x (percent sign - 0025)
+2032   PRIME
+       = minutes, feet
+       x (apostrophe - 0027)
+       x (acute accent - 00B4)
+       x (modifier letter prime - 02B9)
+2033   DOUBLE PRIME
+       = seconds, inches
+       x (quotation mark - 0022)
+       x (modifier letter double prime - 02BA)
+       x (right double quotation mark - 201D)
+       x (ditto mark - 3003)
+       x (double prime quotation mark - 301E)
+       # 2032 2032
+2034   TRIPLE PRIME
+       # 2032 2032 2032
+2035   REVERSED PRIME
+       x (grave accent - 0060)
+2036   REVERSED DOUBLE PRIME
+       x (reversed double prime quotation mark - 301D)
+       # 2035 2035
+2037   REVERSED TRIPLE PRIME
+       # 2035 2035 2035
+2038   CARET
+       x (up arrowhead - 2303)
+2039   SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+       = LEFT POINTING SINGLE GUILLEMET
+       * usually opening, sometimes closing
+       x (less-than sign - 003C)
+       x (left-pointing angle bracket - 2329)
+       x (left angle bracket - 3008)
+203A   SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+       = RIGHT POINTING SINGLE GUILLEMET
+       * usually closing, sometimes opening
+       x (greater-than sign - 003E)
+       x (right-pointing angle bracket - 232A)
+       x (right angle bracket - 3009)
+203B   REFERENCE MARK
+       = Japanese kome
+       = Urdu paragraph separator
+       x (tibetan ku ru kha bzhi mig can - 0FBF)
+203C   DOUBLE EXCLAMATION MARK
+       x (exclamation mark - 0021)
+       # 0021 0021
+203D   INTERROBANG
+       x (exclamation mark - 0021)
+       x (question mark - 003F)
+203E   OVERLINE
+       = SPACING OVERSCORE
+       # 0020 0305
+203F   UNDERTIE (Enotikon)
+       = Greek enotikon
+       x (smile - 2323)
+2040   CHARACTER TIE
+       x (frown - 2322)
+2041   CARET INSERTION POINT
+       * proofreader's mark: insert here
+       x (right semidirect product - 22CC)
+2042   ASTERISM
+2043   HYPHEN BULLET
+2044   FRACTION SLASH
+       = solidus (in typography)
+       * for composing arbitrary fractions
+       x (solidus - 002F)
+       x (division slash - 2215)
+2045   LEFT SQUARE BRACKET WITH QUILL
+2046   RIGHT SQUARE BRACKET WITH QUILL
+2048   QUESTION EXCLAMATION MARK
+       * designed for use in vertical text
+       # 003F 0021
+2049   EXCLAMATION QUESTION MARK
+       * designed for use in vertical text
+       # 0021 003F
+204A   TIRONIAN SIGN ET
+       * Irish Gaelic, ...
+204B   REVERSED PILCROW SIGN
+       x (pilcrow sign - 00B6)
+204C   BLACK LEFTWARDS BULLET
+204D   BLACK RIGHTWARDS BULLET
+@              Deprecated
+206A   INHIBIT SYMMETRIC SWAPPING
+206B   ACTIVATE SYMMETRIC SWAPPING
+206C   INHIBIT ARABIC FORM SHAPING
+206D   ACTIVATE ARABIC FORM SHAPING
+206E   NATIONAL DIGIT SHAPES
+206F   NOMINAL DIGIT SHAPES
+@@     2070    Superscripts and Subscripts     209F
+@              Superscripts
+2070   SUPERSCRIPT ZERO
+       # <super> 0030
+2071   <reserved>
+       x (superscript one - 00B9)
+2072   <reserved>
+       x (superscript two - 00B2)
+2073   <reserved>
+       x (superscript three - 00B3)
+2074   SUPERSCRIPT FOUR
+       # <super> 0034
+2075   SUPERSCRIPT FIVE
+       # <super> 0035
+2076   SUPERSCRIPT SIX
+       # <super> 0036
+2077   SUPERSCRIPT SEVEN
+       # <super> 0037
+2078   SUPERSCRIPT EIGHT
+       # <super> 0038
+2079   SUPERSCRIPT NINE
+       # <super> 0039
+207A   SUPERSCRIPT PLUS SIGN
+       # <super> 002B
+207B   SUPERSCRIPT MINUS
+       # <super> 2212
+207C   SUPERSCRIPT EQUALS SIGN
+       # <super> 003D
+207D   SUPERSCRIPT LEFT PARENTHESIS
+       # <super> 0028
+207E   SUPERSCRIPT RIGHT PARENTHESIS
+       # <super> 0029
+207F   SUPERSCRIPT LATIN SMALL LETTER N
+       # <super> 006E
+@              Subscripts
+2080   SUBSCRIPT ZERO
+       # <sub> 0030
+2081   SUBSCRIPT ONE
+       # <sub> 0031
+2082   SUBSCRIPT TWO
+       # <sub> 0032
+2083   SUBSCRIPT THREE
+       # <sub> 0033
+2084   SUBSCRIPT FOUR
+       # <sub> 0034
+2085   SUBSCRIPT FIVE
+       # <sub> 0035
+2086   SUBSCRIPT SIX
+       # <sub> 0036
+2087   SUBSCRIPT SEVEN
+       # <sub> 0037
+2088   SUBSCRIPT EIGHT
+       # <sub> 0038
+2089   SUBSCRIPT NINE
+       # <sub> 0039
+208A   SUBSCRIPT PLUS SIGN
+       # <sub> 002B
+208B   SUBSCRIPT MINUS
+       # <sub> 2212
+208C   SUBSCRIPT EQUALS SIGN
+       # <sub> 003D
+208D   SUBSCRIPT LEFT PARENTHESIS
+       # <sub> 0028
+208E   SUBSCRIPT RIGHT PARENTHESIS
+       # <sub> 0029
+@@     20A0    Currency Symbols        20CF
+@              Currency symbols
+@+             A number of currency symbols are found in other blocks.
+               x (dollar sign - 0024)
+               x (cent sign - 00A2)
+               x (pound sign - 00A3)
+               x (currency sign - 00A4)
+               x (yen sign - 00A5)
+               x (bengali rupee mark - 09F2)
+               x (bengali rupee sign - 09F3)
+               x (thai currency symbol baht - 0E3F)
+               x (khmer currency symbol riel - 17DB)
+20A0   EURO-CURRENCY SIGN
+       * intended for ECU, but not widely used
+       * historical character, this is NOT the euro!
+       x (euro sign - 20AC)
+20A1   COLON SIGN
+       * Costa Rica, El Salvador
+20A2   CRUZEIRO SIGN
+       * Brazil
+20A3   FRENCH FRANC SIGN
+       * France
+20A4   LIRA SIGN
+       * Italy, Turkey
+       x (pound sign - 00A3)
+20A5   MILL SIGN
+       * USA (1/10 cent)
+20A6   NAIRA SIGN
+       * Nigeria
+20A7   PESETA SIGN
+       * Spain
+20A8   RUPEE SIGN
+       * India
+       # 0052 0073
+20A9   WON SIGN
+       * Korea
+20AA   NEW SHEQEL SIGN
+       * Israel
+20AB   DONG SIGN
+       * Vietnam
+20AC   EURO SIGN
+       * currency sign for the European Monetary Union
+       * euro, not ECU
+       x (euro-currency sign - 20A0)
+20AD   KIP SIGN
+       * Laos
+20AE   TUGRIK SIGN
+       * Mongolia
+       * also transliterated as tugrug, tugric, tugrog, togrog
+20AF   DRACHMA SIGN
+       * Greece
+@@     20D0    Combining Diacritical Marks for Symbols 20FF
+@              Combining diacritical marks for symbols
+20D0   COMBINING LEFT HARPOON ABOVE
+20D1   COMBINING RIGHT HARPOON ABOVE
+       * vector
+20D2   COMBINING LONG VERTICAL LINE OVERLAY
+20D3   COMBINING SHORT VERTICAL LINE OVERLAY
+       * negation
+20D4   COMBINING ANTICLOCKWISE ARROW ABOVE
+20D5   COMBINING CLOCKWISE ARROW ABOVE
+       * rotation
+20D6   COMBINING LEFT ARROW ABOVE
+20D7   COMBINING RIGHT ARROW ABOVE
+       * vector
+20D8   COMBINING RING OVERLAY
+20D9   COMBINING CLOCKWISE RING OVERLAY
+20DA   COMBINING ANTICLOCKWISE RING OVERLAY
+20DB   COMBINING THREE DOTS ABOVE
+       = third derivative
+20DC   COMBINING FOUR DOTS ABOVE
+       = fourth derivative
+@              Enclosing diacritics
+20DD   COMBINING ENCLOSING CIRCLE
+       = JIS composition circle
+       x (white circle - 25CB)
+       x (large circle - 25EF)
+       x (ideographic number zero - 3007)
+20DE   COMBINING ENCLOSING SQUARE
+       x (white square - 25A1)
+20DF   COMBINING ENCLOSING DIAMOND
+       x (white diamond - 25C7)
+20E0   COMBINING ENCLOSING CIRCLE BACKSLASH
+       * prohibition
+@              Additional diacritical mark for symbols
+20E1   COMBINING LEFT RIGHT ARROW ABOVE
+       * tensor
+@              Additional enclosing diacritics
+20E2   COMBINING ENCLOSING SCREEN
+       x (clear screen symbol - 239A)
+20E3   COMBINING ENCLOSING KEYCAP
+
+*/
+
index 53d357c7a1af3e6193f45734447b3f08a6746bd4..ad2520b75d6065f9321b92ef28232c432e83edb5 100755 (executable)
@@ -1,18 +1,18 @@
-//\r
-// charnames.h\r
-//\r
-// A header file that links Unicode character names to character numbers.\r
-// Also, throws in the Macintosh standard glyph names to boot.\r
-//\r
-// by James L. Hammons\r
-//\r
-\r
-extern unsigned char macStdNames[];\r
-extern unsigned char unicodeChars[];\r
-\r
-/*struct unicodeChar\r
-{\r
-  int cNum;\r
-\r
-};*/\r
-\r
+//
+// charnames.h
+//
+// A header file that links Unicode character names to character numbers.
+// Also, throws in the Macintosh standard glyph names to boot.
+//
+// by James L. Hammons
+//
+
+extern unsigned char macStdNames[];
+extern unsigned char unicodeChars[];
+
+/*struct unicodeChar
+{
+  int cNum;
+
+};*/
+
index 00adcd8c05e7ac334180fe586b890fc7511db857..4c601c8392e27ae21dc27fca89ba784fa5d884ce 100755 (executable)
@@ -1,56 +1,56 @@
-//\r
-// TTEDIT.CPP - The TrueType Editor\r
-// by James L. Hammons\r
-// (C) 2004 Underground Software\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  -------------------------------------------------------------\r
-// JLH  08/28/2008  Created this file\r
-//\r
-\r
-// FIXED:\r
-//\r
-// STILL TO BE DONE:\r
-//\r
-// - Fix problem with owned window causing main window refresh problems\r
-//   (ironically enough, it doesn't seem to be a problem anymore...)\r
-//\r
-\r
-#include "charwindow.h"\r
-\r
-\r
-BEGIN_EVENT_TABLE(CharWindow, wxMiniFrame)\r
-       EVT_PAINT(CharWindow::OnPaint)\r
-//     EVT_MOUSE_EVENTS(CharWindow::OnMouseEvent)\r
-END_EVENT_TABLE()\r
-\r
-CharWindow::CharWindow(wxFrame * parent, const wxString &title, const wxPoint &pos,\r
-       const wxSize &size, long style): wxMiniFrame(parent, -1, title, pos, size, style)\r
-{\r
-       Show(false);\r
-}\r
-\r
-CharWindow::~CharWindow()\r
-{\r
-}\r
-\r
-void CharWindow::OnPaint(wxPaintEvent &e)\r
-{\r
-       wxPaintDC dc(this);\r
-//doesnothing  dc.SetBackground(*wxWHITE_BRUSH);\r
-\r
-//     wxMemoryDC memDC;\r
-//     memDC.SelectObject(*bmp);\r
-//     dc.Blit(0, 0, sizeTPBM.x, sizeTPBM.y, &memDC, 0, 0, wxCOPY);\r
-\r
-//     if (prevTool != -1)\r
-//     {\r
-//         //need ul corner of bitmap, ul corner of dest, width/height\r
-//             wxPoint pt(sizeStamp.x * (prevTool & 0x03), sizeStamp.y * (prevTool >> 2));\r
-//             dc.Blit(pt.x, pt.y, sizeStamp.x, sizeStamp.y, &memDC, pt.x, pt.y, wxSRC_INVERT);\r
-//     }\r
-\r
-//     memDC.SelectObject(wxNullBitmap);\r
-}\r
+//
+// TTEDIT.CPP - The TrueType Editor
+// by James L. Hammons
+// (C) 2004 Underground Software
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  08/28/2008  Created this file
+//
+
+// FIXED:
+//
+// STILL TO BE DONE:
+//
+// - Fix problem with owned window causing main window refresh problems
+//   (ironically enough, it doesn't seem to be a problem anymore...)
+//
+
+#include "charwindow.h"
+
+
+BEGIN_EVENT_TABLE(CharWindow, wxMiniFrame)
+       EVT_PAINT(CharWindow::OnPaint)
+//     EVT_MOUSE_EVENTS(CharWindow::OnMouseEvent)
+END_EVENT_TABLE()
+
+CharWindow::CharWindow(wxFrame * parent, const wxString &title, const wxPoint &pos,
+       const wxSize &size, long style): wxMiniFrame(parent, -1, title, pos, size, style)
+{
+       Show(false);
+}
+
+CharWindow::~CharWindow()
+{
+}
+
+void CharWindow::OnPaint(wxPaintEvent &e)
+{
+       wxPaintDC dc(this);
+//doesnothing  dc.SetBackground(*wxWHITE_BRUSH);
+
+//     wxMemoryDC memDC;
+//     memDC.SelectObject(*bmp);
+//     dc.Blit(0, 0, sizeTPBM.x, sizeTPBM.y, &memDC, 0, 0, wxCOPY);
+
+//     if (prevTool != -1)
+//     {
+//         //need ul corner of bitmap, ul corner of dest, width/height
+//             wxPoint pt(sizeStamp.x * (prevTool & 0x03), sizeStamp.y * (prevTool >> 2));
+//             dc.Blit(pt.x, pt.y, sizeStamp.x, sizeStamp.y, &memDC, pt.x, pt.y, wxSRC_INVERT);
+//     }
+
+//     memDC.SelectObject(wxNullBitmap);
+}
index 19fefb2e31ff4e448e9644284d701b717e4e63e9..0f6add1955ee43195d216d5cd7acf95c3507eef1 100755 (executable)
@@ -1,33 +1,33 @@
-//\r
-// CHARWINDOW.H: Header file\r
-//\r
-// by James L. Hammons\r
-// (C) 2008 Underground Software\r
-//\r
-\r
-#ifndef __CHARWINDOW_H__\r
-#define __CHARWINDOW_H__\r
-\r
-#include <wx/wx.h>                                                             // So that whoever uses this can without having\r
-                                                                                               // to pull in a bunch of references manually\r
-#include <wx/minifram.h>\r
-\r
-class CharWindow: public wxMiniFrame\r
-{\r
-       private:\r
-       protected:\r
-       public:\r
-               wxBitmap * bmp;\r
-\r
-               // Constructor and destructor\r
-//             CharWindow(wxFrame * parent, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0);\r
-               CharWindow(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style);\r
-               ~CharWindow(void);\r
-\r
-               void OnPaint(wxPaintEvent &e);\r
-//             void OnMouseEvent(wxMouseEvent &e);\r
-\r
-       DECLARE_EVENT_TABLE()\r
-};\r
-\r
-#endif // __CHARWINDOW_H__\r
+//
+// CHARWINDOW.H: Header file
+//
+// by James L. Hammons
+// (C) 2008 Underground Software
+//
+
+#ifndef __CHARWINDOW_H__
+#define __CHARWINDOW_H__
+
+#include <wx/wx.h>                                                             // So that whoever uses this can without having
+                                                                                               // to pull in a bunch of references manually
+#include <wx/minifram.h>
+
+class CharWindow: public wxMiniFrame
+{
+       private:
+       protected:
+       public:
+               wxBitmap * bmp;
+
+               // Constructor and destructor
+//             CharWindow(wxFrame * parent, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0);
+               CharWindow(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style);
+               ~CharWindow(void);
+
+               void OnPaint(wxPaintEvent &e);
+//             void OnMouseEvent(wxMouseEvent &e);
+
+       DECLARE_EVENT_TABLE()
+};
+
+#endif // __CHARWINDOW_H__
index b165165e505f341d40be42a8289601cf4305758b..fb77b4277a07ddec150f50f2cd050a7e951c948d 100755 (executable)
-//\r
-// DEBUG.CPP: Debugging support\r
-// by James L. Hammons\r
-// (C) 2002 Underground Software\r
-//\r
-//   JLH = James Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  ------------------------------------------------------------\r
-// JLH  07/31/2002  Created this file\r
-// JLH  07/31/2002  Added debug log functions & system error logging functions\r
-// JLH  08/16/2002  Added debug log function for SQL error reporting, made\r
-//                  WriteLogMsg thread safe\r
-// JLH  12/10/2002  Added code to have a background message window\r
-// JLH  05/14/2004  Converted code to C++ (sans ODBC logging)\r
-// JLH  05/15/2005  Converted code to generic C++\r
-//\r
-\r
-//#include <windows.h>\r
-//#include <odbc.h>\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include "debug.h"\r
-\r
-// EQUATES\r
-\r
-//#define USDB_WRITEMESSAGE  WM_USER + 1                       // Display a message on the debug window\r
-\r
-// Function prototypes\r
-\r
-//void CreateDebugWin(void);\r
-//LRESULT CALLBACK DebugWinProc(HWND, UINT, WPARAM, LPARAM);\r
-\r
-// CONSTANTS\r
-\r
-const char logFilename[] = "debug.log";\r
-\r
-// DATA\r
-\r
-FILE * logFile = NULL;\r
-\r
-// UNINITIALIZED DATA\r
-\r
-//CRITICAL_SECTION csLock;                                             // Critical section lock\r
-\r
-//\r
-// Open the debugging log file\r
-//\r
-void OpenDebugLog(void)\r
-{\r
-//     hLogFile = CreateFile(logFilename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,\r
-//             NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL, NULL);\r
-//     InitializeCriticalSection(&csLock);\r
-       logFile = fopen(logFilename, "wb");\r
-#ifdef DEBUGWIN\r
-       CreateDebugWin();\r
-#endif\r
-}\r
-\r
-//\r
-// Close the debugging log file\r
-//\r
-void CloseDebugLog(void)\r
-{\r
-//     CloseHandle(hLogFile);\r
-       fclose(logFile);\r
-//     DeleteCriticalSection(&csLock);\r
-\r
-//     if (hDebugWnd)\r
-//             DestroyWindow(hDebugWnd);\r
-}\r
-\r
-//\r
-// Write a message to the log file\r
-//\r
-/*void WriteLogMsg(char * msg)\r
-{\r
-       if (!msg)                                                                       // Check for valid pointer\r
-               return;\r
-\r
-       EnterCriticalSection(&csLock);\r
-\r
-       if (hLogFile)\r
-               WriteFile(hLogFile, msg, lstrlen(msg), &wfBytesWritten, NULL);\r
-\r
-       if (hDebugWnd)\r
-               SendMessage(hDebugWnd, USDB_WRITEMESSAGE, FALSE, (LPARAM)msg);\r
-\r
-       LeaveCriticalSection(&csLock);\r
-}//*/\r
-\r
-//\r
-// This logger is used mainly to ensure that text gets written to the log file\r
-// even if the program crashes. The performance hit is acceptable in this case!\r
-//\r
-void WriteLogMsg(const char * msg, ...)\r
-{\r
-       if (!msg)                                                                       // Check for valid pointer\r
-               return;\r
-\r
-//     EnterCriticalSection(&csLock);\r
-\r
-       va_list arg;\r
-\r
-       va_start(arg, msg);\r
-//     wvsprintf(str, msg, arg);\r
-       if (logFile)\r
-       {\r
-               vfprintf(logFile, msg, arg);\r
-               fflush(logFile);\r
-       }\r
-\r
-       va_end(arg);\r
-\r
-//     if (hLogFile)\r
-//             WriteFile(hLogFile, str, lstrlen(msg), &wfBytesWritten, NULL);\r
-\r
-//     if (hDebugWnd)\r
-//             SendMessage(hDebugWnd, USDB_WRITEMESSAGE, FALSE, (LPARAM)str);\r
-\r
-//     LeaveCriticalSection(&csLock);\r
-}\r
-\r
-\r
-//\r
-// Display a system error message on the screen\r
-//\r
-/*void DisplaySysError(HWND hWnd)\r
-{\r
-       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL,\r
-               GetLastError(), 1024, pBuf, 0, NULL);\r
-       MessageBox(hWnd, pBuf, errTitle, MB_ICONERROR);\r
-       LocalFree(pBuf);\r
-}\r
-\r
-//\r
-// Create "live log" debug window\r
-//\r
-void CreateDebugWin(void)\r
-{\r
-       WNDCLASS wc;\r
-\r
-       RtlZeroMemory(&wc, sizeof(wc));\r
-       wc.lpfnWndProc = DebugWinProc;\r
-       wc.hInstance = GetModuleHandle(NULL);\r
-       wc.hCursor = LoadCursor(NULL, IDC_ARROW);\r
-       wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);\r
-       wc.lpszClassName = CNDebug;\r
-\r
-       if (!RegisterClass(&wc))\r
-               return;\r
-\r
-       hDebugWnd = CreateWindowEx(NULL, CNDebug, debugWin,\r
-               WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_SYSMENU,\r
-               0, 0, 400, 400, NULL, NULL, NULL, NULL);\r
-}\r
-\r
-//\r
-// Debug "live log" window procedure\r
-//\r
-LRESULT CALLBACK DebugWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
-{\r
-       switch (uMsg)\r
-       {\r
-       // *****************\r
-       // *** WM_CREATE ***\r
-       // *****************\r
-\r
-       case WM_CREATE:\r
-               hEdit1 = CreateWindowEx(NULL, CNEdit, NULL,\r
-                       WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_READONLY | ES_MULTILINE | ES_AUTOVSCROLL,\r
-                       0, 0, 1, 1, hWnd, NULL, NULL, NULL);\r
-               break;\r
-\r
-       // ******************\r
-       // *** WM_DESTROY ***\r
-       // ******************\r
-\r
-       case WM_DESTROY:\r
-               hDebugWnd = NULL;                                               // Just in case user closes it himself...\r
-               break;\r
-\r
-       // ***************\r
-       // *** WM_SIZE ***\r
-       // ***************\r
-\r
-       case WM_SIZE:\r
-               SetWindowPos(hEdit1, NULL, 0, 0, lParam & 0xFFFF, lParam >> 16, SWP_NOMOVE | SWP_NOZORDER);\r
-               break;\r
-\r
-       // *************************\r
-       // *** USDB_WRITEMESSAGE ***\r
-       // *************************\r
-\r
-       case USDB_WRITEMESSAGE:\r
-               SendMessage(hEdit1, EM_SETSEL, -2, -2);\r
-               SendMessage(hEdit1, EM_REPLACESEL, wParam, lParam);\r
-               break;\r
-\r
-       default:\r
-               return DefWindowProc(hWnd, uMsg, wParam, lParam);\r
-       }\r
-\r
-       return 0;\r
-}\r
-//*/\r
+//
+// DEBUG.CPP: Debugging support
+// by James L. Hammons
+// (C) 2002 Underground Software
+//
+//   JLH = James Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  ------------------------------------------------------------
+// JLH  07/31/2002  Created this file
+// JLH  07/31/2002  Added debug log functions & system error logging functions
+// JLH  08/16/2002  Added debug log function for SQL error reporting, made
+//                  WriteLogMsg thread safe
+// JLH  12/10/2002  Added code to have a background message window
+// JLH  05/14/2004  Converted code to C++ (sans ODBC logging)
+// JLH  05/15/2005  Converted code to generic C++
+//
+
+//#include <windows.h>
+//#include <odbc.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "debug.h"
+
+// EQUATES
+
+//#define USDB_WRITEMESSAGE  WM_USER + 1                       // Display a message on the debug window
+
+// Function prototypes
+
+//void CreateDebugWin(void);
+//LRESULT CALLBACK DebugWinProc(HWND, UINT, WPARAM, LPARAM);
+
+// CONSTANTS
+
+const char logFilename[] = "debug.log";
+
+// DATA
+
+FILE * logFile = NULL;
+
+// UNINITIALIZED DATA
+
+//CRITICAL_SECTION csLock;                                             // Critical section lock
+
+//
+// Open the debugging log file
+//
+void OpenDebugLog(void)
+{
+//     hLogFile = CreateFile(logFilename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+//             NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL, NULL);
+//     InitializeCriticalSection(&csLock);
+       logFile = fopen(logFilename, "wb");
+#ifdef DEBUGWIN
+       CreateDebugWin();
+#endif
+}
+
+//
+// Close the debugging log file
+//
+void CloseDebugLog(void)
+{
+//     CloseHandle(hLogFile);
+       fclose(logFile);
+//     DeleteCriticalSection(&csLock);
+
+//     if (hDebugWnd)
+//             DestroyWindow(hDebugWnd);
+}
+
+//
+// Write a message to the log file
+//
+/*void WriteLogMsg(char * msg)
+{
+       if (!msg)                                                                       // Check for valid pointer
+               return;
+
+       EnterCriticalSection(&csLock);
+
+       if (hLogFile)
+               WriteFile(hLogFile, msg, lstrlen(msg), &wfBytesWritten, NULL);
+
+       if (hDebugWnd)
+               SendMessage(hDebugWnd, USDB_WRITEMESSAGE, FALSE, (LPARAM)msg);
+
+       LeaveCriticalSection(&csLock);
+}//*/
+
+//
+// This logger is used mainly to ensure that text gets written to the log file
+// even if the program crashes. The performance hit is acceptable in this case!
+//
+void WriteLogMsg(const char * msg, ...)
+{
+       if (!msg)                                                                       // Check for valid pointer
+               return;
+
+//     EnterCriticalSection(&csLock);
+
+       va_list arg;
+
+       va_start(arg, msg);
+//     wvsprintf(str, msg, arg);
+       if (logFile)
+       {
+               vfprintf(logFile, msg, arg);
+               fflush(logFile);
+       }
+
+       va_end(arg);
+
+//     if (hLogFile)
+//             WriteFile(hLogFile, str, lstrlen(msg), &wfBytesWritten, NULL);
+
+//     if (hDebugWnd)
+//             SendMessage(hDebugWnd, USDB_WRITEMESSAGE, FALSE, (LPARAM)str);
+
+//     LeaveCriticalSection(&csLock);
+}
+
+
+//
+// Display a system error message on the screen
+//
+/*void DisplaySysError(HWND hWnd)
+{
+       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL,
+               GetLastError(), 1024, pBuf, 0, NULL);
+       MessageBox(hWnd, pBuf, errTitle, MB_ICONERROR);
+       LocalFree(pBuf);
+}
+
+//
+// Create "live log" debug window
+//
+void CreateDebugWin(void)
+{
+       WNDCLASS wc;
+
+       RtlZeroMemory(&wc, sizeof(wc));
+       wc.lpfnWndProc = DebugWinProc;
+       wc.hInstance = GetModuleHandle(NULL);
+       wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+       wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
+       wc.lpszClassName = CNDebug;
+
+       if (!RegisterClass(&wc))
+               return;
+
+       hDebugWnd = CreateWindowEx(NULL, CNDebug, debugWin,
+               WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_SYSMENU,
+               0, 0, 400, 400, NULL, NULL, NULL, NULL);
+}
+
+//
+// Debug "live log" window procedure
+//
+LRESULT CALLBACK DebugWinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+       switch (uMsg)
+       {
+       // *****************
+       // *** WM_CREATE ***
+       // *****************
+
+       case WM_CREATE:
+               hEdit1 = CreateWindowEx(NULL, CNEdit, NULL,
+                       WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_READONLY | ES_MULTILINE | ES_AUTOVSCROLL,
+                       0, 0, 1, 1, hWnd, NULL, NULL, NULL);
+               break;
+
+       // ******************
+       // *** WM_DESTROY ***
+       // ******************
+
+       case WM_DESTROY:
+               hDebugWnd = NULL;                                               // Just in case user closes it himself...
+               break;
+
+       // ***************
+       // *** WM_SIZE ***
+       // ***************
+
+       case WM_SIZE:
+               SetWindowPos(hEdit1, NULL, 0, 0, lParam & 0xFFFF, lParam >> 16, SWP_NOMOVE | SWP_NOZORDER);
+               break;
+
+       // *************************
+       // *** USDB_WRITEMESSAGE ***
+       // *************************
+
+       case USDB_WRITEMESSAGE:
+               SendMessage(hEdit1, EM_SETSEL, -2, -2);
+               SendMessage(hEdit1, EM_REPLACESEL, wParam, lParam);
+               break;
+
+       default:
+               return DefWindowProc(hWnd, uMsg, wParam, lParam);
+       }
+
+       return 0;
+}
+//*/
index b53a15dd3d9ae2a8df6f20927c7913d4fa1e4a0e..366af5ac255a8e45034943d0d2b8c71e49b933a8 100755 (executable)
@@ -1,15 +1,15 @@
-//\r
-// DEBUG.H: Debugging support header\r
-// by James L. Hammons\r
-// (C) 2002 Underground Software\r
-//\r
-\r
-// Function prototypes\r
-\r
-void OpenDebugLog(void);\r
-void CloseDebugLog(void);\r
-void WriteLogMsg(const char *, ...);\r
-//void WriteSysMsg(void);\r
-//void WriteSQLMsg(DWORD, DWORD);\r
-//void DisplaySysError(HWND);\r
-\r
+//
+// DEBUG.H: Debugging support header
+// by James L. Hammons
+// (C) 2002 Underground Software
+//
+
+// Function prototypes
+
+void OpenDebugLog(void);
+void CloseDebugLog(void);
+void WriteLogMsg(const char *, ...);
+//void WriteSysMsg(void);
+//void WriteSQLMsg(DWORD, DWORD);
+//void DisplaySysError(HWND);
+
index e16cee9a5be37a6726e562fa1d476b6bcd906817..34b1a06c59c5e15a7065e6d7b6d788d079a06de4 100755 (executable)
-//\r
-// TTEDIT.CPP - The TrueType Editor\r
-// by James L. Hammons\r
-// (C) 2004 Underground Software\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  -------------------------------------------------------------\r
-// JLH  08/28/2008  Created this file\r
-//\r
-\r
-// FIXED:\r
-//\r
-// STILL TO BE DONE:\r
-//\r
-// - Fix bug in Glyphpoints when dragging on an empty canvas or loading a font\r
-// - Fix scrolling, zooming, settings (ini)\r
-//\r
-\r
-// Uncomment this for debugging...\r
-#define DEBUG\r
-#define DEBUGFOO            // Various tool debugging...\r
-#define DEBUGTP                                // Toolpalette debugging...\r
-\r
-#include "editwindow.h"\r
-#include "graphicprimitives.h"\r
-#include "toolwindow.h"\r
-#include "debug.h"\r
-#include "vector.h"\r
-\r
-\r
-BEGIN_EVENT_TABLE(TTEditWindow, wxWindow)\r
-       EVT_PAINT(TTEditWindow::OnPaint)\r
-       EVT_MOUSE_EVENTS(TTEditWindow::OnMouseEvent)\r
-END_EVENT_TABLE()\r
-\r
-TTEditWindow::TTEditWindow(wxFrame * parent, const wxPoint &pos, const wxSize &size, long style):\r
-       wxWindow(parent, -1, pos, size, style | wxFULL_REPAINT_ON_RESIZE),\r
-       app(wxGetApp()), scale(1.0), offsetX(-10), offsetY(-10), tool(TOOLSelect),\r
-       ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1), oldPtNextHighlight(-1),\r
-       polyFirstPoint(true), bmp(NULL)\r
-{ \r
-       SetCursor(*(app.cur[tool]));\r
-       SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF));\r
-\r
-       wxString s;\r
-       s.Printf(_("Zoom: %.2f%%"), scale * 100.0);\r
-       parent->SetStatusText(s, 1);\r
-}\r
-\r
-TTEditWindow::~TTEditWindow(void)\r
-{\r
-       if (bmp)\r
-               delete bmp;\r
-}\r
-\r
-void TTEditWindow::OnPaint(wxPaintEvent &e)\r
-{\r
-       wxPaintDC dc(this);\r
-//Doesn't do crap!\r
-//dc.SetBackground(*wxWHITE_BRUSH);\r
-\r
-// Due to the screwiness of wxWidgets coord system, the origin is ALWAYS\r
-// the upper left corner--regardless of axis orientation, etc...\r
-       wxCoord width, height;\r
-       dc.GetSize(&width, &height);\r
-\r
-       dc.SetDeviceOrigin(-offsetX, height - (-offsetY));\r
-       dc.SetAxisOrientation(true, true);\r
-\r
-// Scrolling can be done by using OffsetViewportOrgEx\r
-// Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform)\r
-// you'd use: % = ViewportExt / WindowExt\r
-// But it makes the window look like crap: fuggetuboutit.\r
-// Instead, we have to scale EVERYTHING by hand. Crap!\r
-// It's not *that* bad, but not as convenient either...\r
-\r
-       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0xFF), 1, wxDOT)));\r
-//     dc.DrawLine(0, 0, 10, 10);\r
-\r
-    // Draw coordinate axes\r
-\r
-       dc.CrossHair(0, 0);\r
-\r
-    // Draw points\r
-\r
-       for(int i=0; i<pts.GetNumPoints(); i++)\r
-       {\r
-               if (i == ptHighlight)\r
-               {\r
-                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));\r
-//                     SelectObject(hdc, hRedPen1);\r
-\r
-                       if (pts.GetOnCurve(i))\r
-                       {\r
-                               DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7);\r
-                               DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9);\r
-                       }\r
-                       else\r
-                       {\r
-                               DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7);\r
-                               DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 9);\r
-                       }\r
-               }\r
-               else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt)\r
-               {\r
-                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0xAF, 0x00), 1, wxSOLID)));\r
-//                     SelectObject(hdc, hGreenPen1);\r
-\r
-                       if (pts.GetOnCurve(i))\r
-                       {\r
-                               DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7);\r
-                               DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9);\r
-                       }\r
-                       else\r
-                       {\r
-                               DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7);\r
-                               DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 9);\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));\r
-//                     SelectObject(hdc, hBlackPen1);\r
-\r
-                       if (pts.GetOnCurve(i))\r
-                               DrawSquareDot(dc, pts.GetX(i), pts.GetY(i));\r
-                       else\r
-                               DrawRoundDot(dc, pts.GetX(i), pts.GetY(i));\r
-               }\r
-\r
-               if (tool == TOOLDelPt && i == ptHighlight)\r
-               {\r
-                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));\r
-//                     SelectObject(hdc, hRedPen1);\r
-//                     MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL);\r
-//                     LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5);\r
-//                     LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness!\r
-//                     MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL);\r
-//                     LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5);\r
-//                     LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!!\r
-                       dc.DrawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5);\r
-                       dc.DrawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5);\r
-               }\r
-       }\r
-\r
-//             SelectObject(hdc, hBlackPen1);\r
-       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));\r
-\r
-       // Draw curve formed by points\r
-\r
-       for(int poly=0; poly<pts.GetNumPolys(); poly++)\r
-       {\r
-               if (pts.GetNumPoints(poly) > 2)\r
-               {\r
-                       // Initial move...\r
-                       // If it's not on curve, then move to it, otherwise move to last point...\r
-\r
-                       wxCoord x, y;\r
-       \r
-                       if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1))\r
-                               x = (wxCoord)pts.GetX(poly, pts.GetNumPoints(poly) - 1), y = (wxCoord)pts.GetY(poly, pts.GetNumPoints(poly) - 1);\r
-                       else\r
-                               x = (wxCoord)pts.GetX(poly, 0), y = (wxCoord)pts.GetY(poly, 0);\r
-       \r
-                       for(int i=0; i<pts.GetNumPoints(poly); i++)\r
-                       {\r
-                               if (pts.GetOnCurve(poly, i))\r
-//                                     LineTo(hdc, pts.GetX(poly, i), pts.GetY(poly, i));\r
-                               {\r
-                                       dc.DrawLine(x, y, pts.GetX(poly, i), pts.GetY(poly, i));\r
-                                       x = (wxCoord)pts.GetX(poly, i), y = (wxCoord)pts.GetY(poly, i);\r
-                               }\r
-                               else\r
-                               {\r
-                                       uint32 prev = pts.GetPrev(poly, i), next = pts.GetNext(poly, i);\r
-                                       float px = pts.GetX(poly, prev), py = pts.GetY(poly, prev),\r
-                                               nx = pts.GetX(poly, next), ny = pts.GetY(poly, next);\r
-       \r
-                                       if (!pts.GetOnCurve(poly, prev))\r
-                                               px = (px + pts.GetX(poly, i)) / 2.0f,\r
-                                               py = (py + pts.GetY(poly, i)) / 2.0f;\r
-       \r
-                                       if (!pts.GetOnCurve(poly, next))\r
-                                               nx = (nx + pts.GetX(poly, i)) / 2.0f,\r
-                                               ny = (ny + pts.GetY(poly, i)) / 2.0f;\r
-       \r
-                                       Bezier(dc, point(px, py), point(pts.GetX(poly, i), pts.GetY(poly, i)), point(nx, ny));\r
-                                       x = (wxCoord)nx, y = (wxCoord)ny;\r
-       \r
-                                       if (pts.GetOnCurve(poly, next))\r
-                                               i++;                                    // Following point is on curve, so move past it\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-//             SelectObject(hdc, oldPen);                              // Restore the stuff we disrupted...\r
-       dc.SetPen(wxNullPen);\r
-//             SelectObject(hdc, oldBrush);\r
-//             EndPaint(hWnd, &ps);\r
-}\r
-\r
-void TTEditWindow::OnMouseEvent(wxMouseEvent &e)\r
-{\r
-#ifdef DEBUGTP\r
-//printf("!!! This window %s focus...!\n", (HasCapture() ? "has" : "doesn't have"));\r
-#endif\r
-       if (e.RightDown())\r
-       {\r
-               // Handle tool palette (NOTE: tool palette deals with RightUp event.)\r
-\r
-               wxPoint pt = ClientToScreen(e.GetPosition());\r
-               app.toolPalette->Move(pt);\r
-               app.toolPalette->Show(true);\r
-               SetCursor(*wxSTANDARD_CURSOR);\r
-               app.toolPalette->SetCursor(*wxSTANDARD_CURSOR);\r
-               app.toolPalette->prevTool = TOOLSelect;\r
-               app.toolPalette->Refresh(false);\r
-               CaptureMouse();\r
-       }\r
-       else if (e.RightUp())\r
-       {\r
-               ToolType newTool = app.toolPalette->FindSelectedTool();//, oldTool = tool;\r
-\r
-               // We only change the tool if a new one was actually selected. Otherwise, we do nothing.\r
-               if (newTool != TOOLNone)\r
-               {\r
-                       tool = newTool;\r
-\r
-                       if (tool == TOOLScroll || tool == TOOLZoom || tool == TOOLAddPoly\r
-                               || tool == TOOLDelPoly)\r
-                               ptHighlight = -1;\r
-\r
-                       if (tool == TOOLAddPoly)\r
-                               polyFirstPoint = true;\r
-               }\r
-\r
-               ReleaseMouse();\r
-               app.toolPalette->Show(false);\r
-               SetCursor(*(app.cur[tool]));\r
-       }\r
-       else if (e.LeftDown())\r
-       {\r
-               if (tool == TOOLScroll || tool == TOOLZoom)\r
-                       CaptureMouse();                                         // Make sure we capture the mouse when in scroll/zoom mode\r
-               else if (tool == TOOLAddPt)             // "Add Point" tool\r
-               {\r
-                       if (pts.GetNumPoints() > 0)\r
-                       {\r
-                               wxPoint pt = GetAdjustedMousePosition(e);\r
-                               pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (e.ShiftDown() | e.ControlDown() ? false : true));\r
-                               ptHighlight = ptNextHighlight;\r
-                               Refresh();\r
-                       }\r
-               }\r
-               else if (tool == TOOLAddPoly)   // "Add Poly" tool\r
-               {\r
-#ifdef DEBUGFOO\r
-WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints());\r
-#endif\r
-                       if (polyFirstPoint)\r
-                       {\r
-                               polyFirstPoint = false;\r
-                               pts.AddNewPolyAtEnd();\r
-                       }\r
-\r
-                       wxPoint pt = GetAdjustedMousePosition(e);\r
-                       // Append a point to the end of the structure\r
-                       pts += IPoint(pt.x, pt.y, (e.ShiftDown() | e.ControlDown() ? false : true));\r
-                       ptHighlight = pts.GetNumPoints() - 1;\r
-                       Refresh();\r
-#ifdef DEBUGFOO\r
-WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumPoints());\r
-#endif\r
-               }\r
-               else if (tool == TOOLSelect || tool == TOOLPolySelect)\r
-               {\r
-                       if (pts.GetNumPoints() > 0)\r
-                       {\r
-                               pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));\r
-                               WarpPointer(pt.x, pt.y);\r
-\r
-                               if (e.ShiftDown() | e.ControlDown())\r
-                                       pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight));\r
-                       }\r
-               }\r
-               else if (tool == TOOLDelPt)\r
-               {\r
-                       if (pts.GetNumPoints() > 0)\r
-//Or could use:\r
-//                     if (ptHighlight != -1)\r
-                       {\r
-//This assumes that WM_MOUSEMOVE happens before this!\r
-//The above commented out line should take care of this contingency... !!! FIX !!!\r
-                               pts.DeletePoint(ptHighlight);\r
-                               Refresh();\r
-                       }\r
-               }\r
-       }\r
-       else if (e.LeftUp())\r
-       {\r
-//             mouseDown = false;\r
-\r
-               if (tool == TOOLScroll || tool == TOOLZoom)\r
-                       ReleaseMouse();\r
-       }\r
-       else if (e.Dragging())\r
-       {\r
-               if (e.RightIsDown())\r
-               {\r
-                       ToolType newTool = app.toolPalette->FindSelectedTool();\r
-\r
-                       if (newTool != app.toolPalette->prevTool)\r
-                       {\r
-                               app.toolPalette->prevTool = newTool;\r
-                               app.toolPalette->Refresh(false);\r
-                       }\r
-\r
-                       return;\r
-               }\r
-\r
-               if (e.MiddleIsDown())\r
-               {\r
-                   // Calc offset from previous point\r
-                       pt = e.GetPosition();\r
-                       ptOffset.x = pt.x - ptPrevious.x,\r
-                       ptOffset.y = pt.y - ptPrevious.y;\r
-\r
-// Then multiply it by the scaling factor. Whee!\r
-                       // This looks wacky because we're using screen coords for the offset...\r
-                       // Otherwise, we would subtract both offsets!\r
-                       offsetX -= ptOffset.x, offsetY += ptOffset.y;\r
-                       Refresh();\r
-\r
-                       return;\r
-               }\r
-\r
-//             if (e.LeftIsDown())\r
-//             {\r
-#if 0\r
-                       if (tool == TOOLScroll)\r
-                       {\r
-                           // Extract current point from lParam/calc offset from previous point\r
-\r
-                               pt = e.GetPosition();\r
-                               ptOffset.x = pt.x - ptPrevious.x,\r
-                               ptOffset.y = pt.y - ptPrevious.y;\r
-\r
-                               // NOTE: OffsetViewportOrg operates in DEVICE UNITS...\r
-\r
-//Seems there's no equivalent for this in wxWidgets...!\r
-//!!! FIX !!!\r
-//                             hdc = GetDC(hWnd);\r
-//                             OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL);\r
-//                             ReleaseDC(hWnd, hdc);\r
-\r
-// this shows that it works, so the logic above must be faulty...\r
-// And it is. It should convert the coords first, then do the subtraction to figure the offset...\r
-// Above: DONE\r
-// Then multiply it by the scaling factor. Whee!\r
-                               // This looks wacky because we're using screen coords for the offset...\r
-                               // Otherwise, we would subtract both offsets!\r
-                               offsetX -= ptOffset.x, offsetY += ptOffset.y;\r
-                               Refresh();\r
-                       }\r
-                       else\r
-#endif\r
- if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect)\r
-                       {\r
-                               if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch.\r
-                               {\r
-//temporary, for testing. BTW, Select drag bug is here...!\r
-#if 0\r
-                                       wxPoint pt2 = GetAdjustedMousePosition(e);\r
-                                       pts.SetXY(ptHighlight, pt2.x, pt2.y);\r
-                                       Refresh();\r
-#endif\r
-                               }\r
-                       }\r
-                       else if (tool == TOOLPolySelect)\r
-                       {\r
-                               if (pts.GetNumPoints() > 0)\r
-                               {\r
-                                       wxPoint pt2 = GetAdjustedMousePosition(e);\r
-                                       // Should also set onCurve here as well, depending on keystate\r
-//Or should we?\r
-                                       pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight));\r
-                                       Refresh();\r
-                               }\r
-                       }\r
-//             }\r
-\r
-               ptPrevious = pt;\r
-       }\r
-       else if (e.Moving())\r
-       {\r
-//             else    // Moving, not dragging...\r
-//             {\r
-                       if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt\r
-                               || tool == TOOLPolySelect)// || tool == TOOLAddPoly)\r
-                       {\r
-                               wxPoint pt2 = GetAdjustedMousePosition(e);\r
-                               double closest = 1.0e+99;\r
-\r
-                               for(int i=0; i<pts.GetNumPoints(); i++)\r
-                               {\r
-                                       double dist = ((pt2.x - pts.GetX(i)) * (pt2.x - pts.GetX(i)))\r
-                                               + ((pt2.y - pts.GetY(i)) * (pt2.y - pts.GetY(i)));\r
-\r
-                                       if (dist < closest)\r
-                                               closest = dist, ptHighlight = i;\r
-                               }\r
-\r
-                               if (ptHighlight != oldPtHighlight)\r
-                               {\r
-                                       oldPtHighlight = ptHighlight;\r
-                                       Refresh();\r
-                               }\r
-\r
-                               // What follows here looks like voodoo, but is really simple. What we do is\r
-                               // check to see if the mouse point has a perpendicular intersection with any of\r
-                               // the line segments. If it does, calculate the length of the perpendicular\r
-                               // and choose the smallest length. If there is no perpendicular, then choose the\r
-                               // length of line connecting the closer of either the first endpoint or the\r
-                               // second and choose the smallest of those.\r
-\r
-                               // There is one bit of math that looks like voodoo to me ATM--will explain once\r
-                               // I understand it better (the calculation of the length of the perpendicular).\r
-\r
-                               if (pts.GetNumPoints() > 1 && tool == TOOLAddPt)\r
-                               {\r
-                                       double smallest = 1.0e+99;\r
-\r
-                                       for(int i=0; i<pts.GetNumPoints(); i++)\r
-                                       {\r
-                                               int32 p1x = pts.GetX(i), p1y = pts.GetY(i),\r
-                                                       p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i));\r
-\r
-                                               vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x, pt2.y, 0, p1x, p1y, 0),\r
-                                                       v2(pt2.x, pt2.y, 0, p2x, p2y, 0);\r
-                                               double pp = ls.dot(v1) / ls.length(), dist;\r
-// Geometric interpretation:\r
-// pp is the paremeterized point on the vector ls where the perpendicular intersects ls.\r
-// If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls,\r
-// then the perpendicular lies beyond the 2nd endpoint.\r
-\r
-                                               if (pp < 0.0)\r
-                                                       dist = v1.length();\r
-                                               else if (pp > ls.length())\r
-                                                       dist = v2.length();\r
-                                               else                                    // distance = ?Det?(ls, v1) / |ls|\r
-                                                       dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.length());\r
-\r
-//The answer to the above looks like it might be found here:\r
-//\r
-//If the segment endpoints are s and e, and the point is p, then the test for the perpendicular\r
-//intercepting the segment is equivalent to insisting that the two dot products {s-e}.{s-p} and\r
-//{e-s}.{e-p} are both non-negative.  Perpendicular distance from the point to the segment is\r
-//computed by first computing the area of the triangle the three points form, then dividing by the\r
-//length of the segment.  Distances are done just by the Pythagorean theorem.  Twice the area of the\r
-//triangle formed by three points is the determinant of the following matrix:\r
-//\r
-//sx sy 1\r
-//ex ey 1\r
-//px py 1\r
-//\r
-//(???) By translating the start point to the origin, this can be rewritten as:\r
-//By subtracting row 1 from all rows, you get the following:\r
-//\r
-//0         0         0\r
-//(ex - sx) (ey - sy) 0\r
-//(px - sx) (py - sy) 0\r
-//\r
-//which greatly simplifies the calculation of the determinant.\r
-\r
-                                               if (dist < smallest)\r
-                                                       smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i;\r
-                                       }\r
-\r
-                                       if (ptNextHighlight != oldPtNextHighlight)\r
-                                       {\r
-                                               oldPtNextHighlight = ptNextHighlight;\r
-                                               Refresh();\r
-                                       }\r
-                               }\r
-                       }\r
-//             }\r
-\r
-               ptPrevious = e.GetPosition();\r
-       }\r
-}\r
-\r
-wxPoint TTEditWindow::GetAdjustedMousePosition(wxMouseEvent &e)\r
-{\r
-       wxCoord width, height;\r
-       wxClientDC dc(this);\r
-\r
-       dc.GetSize(&width, &height);\r
-       dc.SetDeviceOrigin(-offsetX, height - (-offsetY));\r
-       dc.SetAxisOrientation(true, true);\r
-\r
-#if 0\r
-wxStatusBar * sb = ((wxFrame *)GetParent())->GetStatusBar();\r
-wxString s;\r
-s.Printf("Logical mouse pos: %d, %d (%d, %d)", pt.x, pt.y, width, height);\r
-sb->SetStatusText(s);\r
-#endif\r
-\r
-       return e.GetLogicalPosition(dc);\r
-}\r
-\r
-wxPoint TTEditWindow::GetAdjustedClientPosition(wxCoord x, wxCoord y)\r
-{\r
-       wxCoord width, height;\r
-       wxClientDC dc(this);\r
-\r
-       dc.GetSize(&width, &height);\r
-       dc.SetDeviceOrigin(-offsetX, height - (-offsetY));\r
-       dc.SetAxisOrientation(true, true);\r
-\r
-       return wxPoint(dc.LogicalToDeviceX(x), dc.LogicalToDeviceY(y));\r
-}\r
-\r
-\r
-#if 0\r
-\r
-!!! OLD STUFF !!!\r
-\r
-\r
-LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)\r
-{\r
-       RECT rc1, rc2;\r
-       HDC hdc;\r
-       POINT pt, ptOffset;\r
-       SIZE sz;\r
-       PAINTSTRUCT ps;\r
-\r
-       switch (msgID)\r
-       {\r
-       case WM_CREATE:\r
-\r
-               MiscCenterWnd(hWnd, GetDesktopWindow());\r
-               InitCommonControls();\r
-               hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, statusBarTxt, hWnd, ID_STATUSBAR);\r
-\r
-               if (!hStatusBar)\r
-                       return -1;\r
-\r
-// clean this crap up!\r
-// well, the only crappy thing here is using a POINT as an int array, but otherwise, this is OK\r
-               wsprintf(strBuf, zoom, 1000);\r
-               hdc = GetDC(hWnd);\r
-               GetTextExtentPoint32(hdc, strBuf, lstrlen(strBuf), &sz);\r
-               ReleaseDC(hWnd, hdc);\r
-               zoomWndWidth = sz.cx;\r
-               wsprintf(strBuf, zoom, 100);\r
-\r
-               GetClientRect(hWnd, &rc1);\r
-               pt.x = rc1.right - zoomWndWidth, pt.y = -1;\r
-               SendMessage(hStatusBar, SB_SETPARTS, 2, (LPARAM)&pt);\r
-               SendMessage(hStatusBar, SB_SETTEXT, (0 | SBT_NOBORDERS), (LPARAM)statusBarTxt);\r
-               SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM)strBuf);\r
-\r
-               hToolBar = CreateToolbarEx(hWnd, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS,\r
-                       IDR_TOOLBAR1, 3, hInst, IDB_TOOLBAR1, tbButtons, 4, 16, 16, 16, 16, sizeof(TBBUTTON));\r
-\r
-               if (!hToolBar)\r
-                       return -1;\r
-\r
-               CreateNewDoc();\r
-\r
-// The following can only be done because we use a private DC (using "CS_OWNDC")\r
-// (Is that true???)\r
-// Set the mapping to draw the character so it fits in the viewport...\r
-               hdc = GetDC(hWnd);\r
-               GetClientRect(hWnd, &rc1);\r
-               GetClientRect(hStatusBar, &rc2);\r
-               rc1.bottom -= rc2.bottom;\r
-               SetMapMode(hdc, MM_ISOTROPIC);\r
-               SetWindowExtEx(hdc, rc1.right, rc1.bottom, NULL);\r
-               SetViewportExtEx(hdc, rc1.right, -rc1.bottom, NULL);\r
-               SetViewportOrgEx(hdc, 0, rc1.bottom, NULL);\r
-               ReleaseDC(hWnd, hdc);\r
-               break;\r
-\r
-       case WM_CLOSE:\r
-\r
-               if (SaveChanges())\r
-               {\r
-                       wpM.length = wpC.length = sizeof(WINDOWPLACEMENT);\r
-                       GetWindowPlacement(hMainWnd, &wpM);\r
-                       GetWindowPlacement(hCharWnd, &wpC);\r
-\r
-                       if (!IsWindowVisible(hCharWnd))         // Needed because Windows lies about visibility\r
-                               wpC.showCmd = SW_HIDE;\r
-\r
-                       hdc = GetDC(hWnd);\r
-                       GetViewportOrgEx(hdc, &ptVPM);\r
-                       ReleaseDC(hWnd, hdc);\r
-\r
-                       DestroyWindow(hWnd);\r
-               }\r
-\r
-               break;\r
-\r
-       case WM_DESTROY:\r
-\r
-               PostQuitMessage(0);\r
-               break;\r
-\r
-       case WM_NCLBUTTONDOWN:\r
-\r
-               if (wParam == HTCAPTION)\r
-               {\r
-                       NCMouseDown = true;\r
-                       GetWindowRect(hMainWnd, &rc1);\r
-                       GetWindowRect(hCharWnd, &rc2);\r
-                       ptWinOffset.x = rc2.left - rc1.left;\r
-                       ptWinOffset.y = rc2.top - rc1.top;\r
-               }\r
-                   \r
-               // Let Windows do its thing with this msg, or weird things will happen...\r
-\r
-               DefWindowProc(hWnd, msgID, wParam, lParam);\r
-               NCMouseDown = false;\r
-               break;\r
-\r
-       case WM_WINDOWPOSCHANGING:\r
-\r
-               if (NCMouseDown)\r
-               {\r
-                       WINDOWPOS * wp = (WINDOWPOS *)lParam;\r
-\r
-                       if (wp->hwnd == hMainWnd && !(wp->flags & SWP_NOMOVE))\r
-                               SetWindowPos(hCharWnd, 0, wp->x + ptWinOffset.x, wp->y + ptWinOffset.y,\r
-                                               0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);\r
-               }\r
-\r
-               return DefWindowProc(hWnd, msgID, wParam, lParam);      // Seems this is needed... Bleah!\r
-\r
-       case WM_PAINT:\r
-       {\r
-               hdc = BeginPaint(hWnd, &ps);\r
-\r
-// Scrolling can be done by using OffsetViewportOrgEx\r
-// Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform)\r
-// you'd use: % = ViewportExt / WindowExt\r
-// But it makes the window look like crap: fuggetuboutit.\r
-// Instead, we have to scale EVERYTHING by hand. Crap!\r
-\r
-               // Apparently, you *must* save the individual object types (pen, brush, etc.)\r
-\r
-               HGDIOBJ oldPen = SelectObject(hdc, hBluePen1),\r
-                       oldBrush = SelectObject(hdc, hNullBrush);\r
-\r
-           // Draw coordinate axes\r
-\r
-               MoveToEx(hdc, 0, -32000, NULL);\r
-               LineTo(hdc, 0, 32000);\r
-               MoveToEx(hdc, -32000, 0, NULL);\r
-               LineTo(hdc, 32000, 0);\r
-\r
-           // Draw points\r
-\r
-               for(int i=0; i<pts.GetNumPoints(); i++)\r
-               {\r
-                       if (i == ptHighlight)\r
-                       {\r
-                               SelectObject(hdc, hRedPen1);\r
-\r
-                               if (pts.GetOnCurve(i))\r
-                               {\r
-                                       DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 7);\r
-                                       DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 9);\r
-                               }\r
-                               else\r
-                               {\r
-                                       DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 7);\r
-                                       DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 9);\r
-                               }\r
-                       }\r
-                       else if ((i == ptHighlight || i == ptNextHighlight) && currentTool == TOOLAddPt)\r
-                       {\r
-                               SelectObject(hdc, hGreenPen1);\r
-\r
-                               if (pts.GetOnCurve(i))\r
-                               {\r
-                                       DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 7);\r
-                                       DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 9);\r
-                               }\r
-                               else\r
-                               {\r
-                                       DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 7);\r
-                                       DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 9);\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               SelectObject(hdc, hBlackPen1);\r
-\r
-                               if (pts.GetOnCurve(i))\r
-                                       DrawSquareDot(hdc, pts.GetX(i), pts.GetY(i));\r
-                               else\r
-                                       DrawRoundDot(hdc, pts.GetX(i), pts.GetY(i));\r
-                       }\r
-\r
-                       if (currentTool == TOOLDelPt && i == ptHighlight)\r
-                       {\r
-                               SelectObject(hdc, hRedPen1);\r
-                               MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL);\r
-                               LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5);\r
-                               LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness!\r
-                               MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL);\r
-                               LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5);\r
-                               LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!!\r
-                       }\r
-               }\r
-\r
-               SelectObject(hdc, hBlackPen1);\r
-\r
-               // Draw curve formed by points\r
-\r
-               for(int poly=0; poly<pts.GetNumPolys(); poly++)\r
-               {\r
-                       if (pts.GetNumPoints(poly) > 2)\r
-                       {\r
-                               // Initial move...\r
-                               // If it's not on curve, then move to it, otherwise move to last point...\r
-       \r
-                               if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1))\r
-                                       MoveToEx(hdc, pts.GetX(poly, pts.GetNumPoints(poly) - 1), pts.GetY(poly, pts.GetNumPoints(poly) - 1), NULL);\r
-                               else\r
-                                       MoveToEx(hdc, pts.GetX(poly, 0), pts.GetY(poly, 0), NULL);\r
-       \r
-                               for(int i=0; i<pts.GetNumPoints(poly); i++)\r
-                               {\r
-                                       if (pts.GetOnCurve(poly, i))\r
-                                               LineTo(hdc, pts.GetX(poly, i), pts.GetY(poly, i));\r
-                                       else\r
-                                       {\r
-                                               uint32 prev = pts.GetPrev(poly, i), next = pts.GetNext(poly, i);\r
-                                               float px = pts.GetX(poly, prev), py = pts.GetY(poly, prev),\r
-                                                       nx = pts.GetX(poly, next), ny = pts.GetY(poly, next);\r
-       \r
-                                               if (!pts.GetOnCurve(poly, prev))\r
-                                                       px = (px + pts.GetX(poly, i)) / 2.0f,\r
-                                                       py = (py + pts.GetY(poly, i)) / 2.0f;\r
-       \r
-                                               if (!pts.GetOnCurve(poly, next))\r
-                                                       nx = (nx + pts.GetX(poly, i)) / 2.0f,\r
-                                                       ny = (ny + pts.GetY(poly, i)) / 2.0f;\r
-       \r
-                                               Bezier(hdc, point(px, py), point(pts.GetX(poly, i), pts.GetY(poly, i)), point(nx, ny));\r
-       \r
-                                               if (pts.GetOnCurve(poly, next))\r
-                                                       i++;                                    // Following point is on curve, so move past it\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-\r
-               SelectObject(hdc, oldPen);                              // Restore the stuff we disrupted...\r
-               SelectObject(hdc, oldBrush);\r
-               EndPaint(hWnd, &ps);\r
-               break;\r
-       }\r
-       case WM_SIZE:\r
-\r
-               // Apparently this is needed since these windows don't update themselves.\r
-               SendMessage(hStatusBar, msgID, wParam, lParam);\r
-               SendMessage(hToolBar, msgID, wParam, lParam);\r
-\r
-               // This is needed to make the 2nd status pane visible\r
-               GetClientRect(hWnd, &rc1);\r
-               pt.x = rc1.right - zoomWndWidth, pt.y = -1;\r
-               SendMessage(hStatusBar, SB_SETPARTS, 2, (LPARAM)&pt);\r
-               break;\r
-\r
-       case WM_RBUTTONDOWN:\r
-\r
-               GetCursorPos(&pt);\r
-               SetWindowPos(hToolPalWnd, 0, pt.x, pt.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);\r
-               SetFocus(hToolPalWnd);\r
-               SetCapture(hToolPalWnd);                                // Ensure tool palette gets RButtonUp\r
-               SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));        // Tool pallete has "regular" cursor\r
-               break;\r
-\r
-       case WM_LBUTTONDOWN:\r
-\r
-               mouseDown = true;\r
-\r
-               if (currentTool == TOOLScroll || currentTool == TOOLZoom)\r
-                       SetCapture(hWnd);                                       // Make sure we capture the mouse when in scroll/zoom mode\r
-               else if (currentTool == TOOLAddPt)              // "Add Point" tool\r
-               {\r
-                       if (pts.GetNumPoints() > 0)\r
-                       {\r
-//Do we really need to put a cap on this???\r
-//Maybe...\r
-//                             if (pts.GetNumPoints() < 16)\r
-//                             {\r
-                               pt.x = lParam & 0xFFFF, pt.y = lParam >> 16;\r
-                               hdc = GetDC(hWnd);\r
-                               DPtoLP(hdc, &pt, 1);\r
-                               pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true));\r
-                               ptHighlight = ptNextHighlight;\r
-                               ReleaseDC(hWnd, hdc);\r
-                               InvalidateRect(hWnd, NULL, TRUE);\r
-//                             }\r
-                       }\r
-               }\r
-               else if (currentTool == TOOLAddPoly)    // "Add Poly" tool\r
-               {\r
-#ifdef DEBUGFOO\r
-wsprintf(strBuf, "Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints());\r
-WriteLogMsg(strBuf);\r
-#endif\r
-                       if (polyFirstPoint)\r
-                       {\r
-                               polyFirstPoint = false;\r
-                               pts.AddNewPolyAtEnd();\r
-                       }\r
-\r
-//Do we really need to put a cap on this???\r
-//Maybe...\r
-//                     if (pts.GetNumPoints() < 16)\r
-//                     {\r
-                       pt.x = lParam & 0xFFFF, pt.y = lParam >> 16;\r
-                       hdc = GetDC(hWnd);\r
-                       DPtoLP(hdc, &pt, 1);\r
-                       ReleaseDC(hWnd, hdc);\r
-                       // Append a point to the end of the structure\r
-                       pts += IPoint(pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true));\r
-ptHighlight = pts.GetNumPoints() - 1;\r
-                       InvalidateRect(hWnd, NULL, TRUE);\r
-//                     }\r
-#ifdef DEBUGFOO\r
-wsprintf(strBuf, " --> [# polys: %u, # points: %u]\xD\xA", pts.GetNumPolys(), pts.GetNumPoints());\r
-WriteLogMsg(strBuf);\r
-#endif\r
-               }\r
-               else if (currentTool == TOOLSelect || currentTool == TOOLPolySelect)\r
-               {\r
-                       if (pts.GetNumPoints() > 0)\r
-                       {\r
-                               pt.x = pts.GetX(ptHighlight), pt.y = pts.GetY(ptHighlight);\r
-                               hdc = GetDC(hWnd);\r
-                               LPtoDP(hdc, &pt, 1);\r
-                               ClientToScreen(hWnd, &pt);\r
-                               SetCursorPos(pt.x, pt.y);\r
-                               ReleaseDC(hWnd, hdc);\r
-\r
-                               if (wParam & (MK_SHIFT | MK_CONTROL))\r
-                                       pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight));\r
-                       }\r
-               }\r
-               else if (currentTool == TOOLDelPt)\r
-               {\r
-                       if (pts.GetNumPoints() > 0)\r
-//Or could use:\r
-//                     if (ptHighlight != -1)\r
-                       {\r
-//This assumes that WM_MOUSEMOVE happens before this!\r
-//The above commented out line should take care of this contingency... !!! FIX !!!\r
-                               pts.DeletePoint(ptHighlight);\r
-                               InvalidateRect(hWnd, NULL, TRUE);\r
-                       }\r
-               }\r
-\r
-               break;\r
-\r
-       case WM_LBUTTONUP:\r
-\r
-               mouseDown = false;\r
-\r
-               if (currentTool == TOOLScroll || currentTool == TOOLZoom)\r
-                       ReleaseCapture();\r
-\r
-               break;\r
-\r
-       case WM_MOUSEMOVE:\r
-\r
-               SetCursor(hCur[currentTool]);\r
-\r
-           // Extract current point from lParam/calc offset from previous point\r
-\r
-               pt.x = lParam & 0xFFFF, pt.y = lParam >> 16;\r
-               ptOffset.x = pt.x - ptPrevious.x,\r
-               ptOffset.y = pt.y - ptPrevious.y;\r
-\r
-               if (mouseDown)\r
-               {\r
-                       if (currentTool == TOOLScroll)\r
-                       {\r
-                               // NOTE: OffsetViewportOrg operates in DEVICE UNITS...\r
-\r
-                               hdc = GetDC(hWnd);\r
-                               OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL);\r
-                               ReleaseDC(hWnd, hdc);\r
-\r
-// this shows that it works, so the logic above must be faulty...\r
-// And it is. It should convert the coords first, then do the subtraction to figure the offset...\r
-// Above: DONE\r
-// Then multiply it by the scaling factor. Whee!\r
-\r
-                               InvalidateRect(hWnd, NULL, TRUE);\r
-//                             SendMessage(hWnd, WM_PAINT, NULL, NULL);\r
-                       }\r
-                       else if (currentTool == TOOLAddPt || currentTool == TOOLAddPoly || currentTool == TOOLSelect)\r
-                       {\r
-                               if (currentTool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch.\r
-                               {\r
-                                       POINT pt2;\r
-                                       pt2.x = pt.x, pt2.y = pt.y;\r
-                                       // Should also set onCurve here as well, depending on keystate\r
-//Or should we?\r
-                                       hdc = GetDC(hWnd);\r
-                                       DPtoLP(hdc, &pt2, 1);\r
-                                       pts.SetXY(ptHighlight, pt2.x, pt2.y);\r
-                                       ReleaseDC(hWnd, hdc);\r
-                                       InvalidateRect(hWnd, NULL, TRUE);\r
-                               }\r
-                       }\r
-                       else if (currentTool == TOOLPolySelect)\r
-                       {\r
-                               if (pts.GetNumPoints() > 0)\r
-                               {\r
-                                       POINT pt2;\r
-                                       pt2.x = pt.x, pt2.y = pt.y;\r
-                                       // Should also set onCurve here as well, depending on keystate\r
-//Or should we?\r
-                                       hdc = GetDC(hWnd);\r
-                                       DPtoLP(hdc, &pt2, 1);\r
-                                       pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight));\r
-                                       ReleaseDC(hWnd, hdc);\r
-                                       InvalidateRect(hWnd, NULL, TRUE);\r
-                               }\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       if (currentTool == TOOLSelect || currentTool == TOOLDelPt || currentTool == TOOLAddPt\r
-                               || currentTool == TOOLPolySelect)// || currentTool == TOOLAddPoly)\r
-                       {\r
-                               POINT pt2;\r
-                               pt2.x = pt.x, pt2.y = pt.y;\r
-                               hdc = GetDC(hWnd);\r
-                               DPtoLP(hdc, &pt2, 1);\r
-                               ReleaseDC(hWnd, hdc);\r
-\r
-                               double closest = 1.0e+99;\r
-\r
-                               for(int i=0; i<pts.GetNumPoints(); i++)\r
-                               {\r
-                                       double dist = ((pt2.x - pts.GetX(i)) * (pt2.x - pts.GetX(i)))\r
-                                               + ((pt2.y - pts.GetY(i)) * (pt2.y - pts.GetY(i)));\r
-\r
-                                       if (dist < closest)\r
-                                               closest = dist, ptHighlight = i;\r
-                               }\r
-\r
-                               if (ptHighlight != oldPtHighlight)\r
-                               {\r
-                                       oldPtHighlight = ptHighlight;\r
-                                       InvalidateRect(hWnd, NULL, TRUE);\r
-                               }\r
-\r
-                               // What follows here looks like voodoo, but is really simple. What we do is\r
-                               // check to see if the mouse point has a perpendicular intersection with any of\r
-                               // the line segments. If it does, calculate the length of the perpendicular\r
-                               // and choose the smallest length. If there is no perpendicular, then choose the\r
-                               // length of line connecting the closer of either the first endpoint or the\r
-                               // second and choose the smallest of those.\r
-\r
-                               // There is one bit of math that looks like voodoo to me ATM--will explain once\r
-                               // I understand it better (the calculation of the length of the perpendicular).\r
-\r
-                               if (pts.GetNumPoints() > 1 && currentTool == TOOLAddPt)\r
-                               {\r
-                                       double smallest = 1.0e+99;\r
-\r
-                                       for(int i=0; i<pts.GetNumPoints(); i++)\r
-                                       {\r
-                                               int32 p1x = pts.GetX(i), p1y = pts.GetY(i),\r
-                                                       p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i));\r
-\r
-                                               vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x, pt2.y, 0, p1x, p1y, 0),\r
-                                                       v2(pt2.x, pt2.y, 0, p2x, p2y, 0);\r
-                                               double pp = ls.dot(v1) / ls.length(), dist;\r
-// Geometric interpretation:\r
-// pp is the paremeterized point on the vector ls where the perpendicular intersects ls.\r
-// If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls,\r
-// then the perpendicular lies beyond the 2nd endpoint.\r
-\r
-                                               if (pp < 0.0)\r
-                                                       dist = v1.length();\r
-                                               else if (pp > ls.length())\r
-                                                       dist = v2.length();\r
-                                               else                                    // distance = ?Det?(ls, v1) / |ls|\r
-                                                       dist = abs((ls.x * v1.y - v1.x * ls.y) / ls.length());\r
-\r
-//The answer to the above looks like it might be found here:\r
-//\r
-//If the segment endpoints are s and e, and the point is p, then the test for the perpendicular\r
-//intercepting the segment is equivalent to insisting that the two dot products {s-e}.{s-p} and\r
-//{e-s}.{e-p} are both non-negative.  Perpendicular distance from the point to the segment is\r
-//computed by first computing the area of the triangle the three points form, then dividing by the\r
-//length of the segment.  Distances are done just by the Pythagorean theorem.  Twice the area of the\r
-//triangle formed by three points is the determinant of the following matrix:\r
-//\r
-//sx sy 1\r
-//ex ey 1\r
-//px py 1\r
-//\r
-//(???) By translating the start point to the origin, this can be rewritten as:\r
-//By subtracting row 1 from all rows, you get the following:\r
-//\r
-//0         0         0\r
-//(ex - sx) (ey - sy) 0\r
-//(px - sx) (py - sy) 0\r
-//\r
-//which greatly simplifies the calculation of the determinant.\r
-\r
-                                               if (dist < smallest)\r
-                                                       smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i;\r
-                                       }\r
-\r
-                                       if (ptNextHighlight != oldPtNextHighlight)\r
-                                       {\r
-                                               oldPtNextHighlight = ptNextHighlight;\r
-                                               InvalidateRect(hWnd, NULL, TRUE);\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-\r
-               ptPrevious.x = pt.x, ptPrevious.y = pt.y;\r
-\r
-               break;\r
-\r
-       case WM_NOTIFY:\r
-\r
-               if (((NMHDR *)lParam)->code == TTN_NEEDTEXT)\r
-               {\r
-                       LoadString(hInst, ((TOOLTIPTEXT *)lParam)->hdr.idFrom + 0x80, toolTipTxt, 16);\r
-                       ((TOOLTIPTEXT *)lParam)->lpszText = toolTipTxt;\r
-               }\r
-\r
-               break;\r
-\r
-       case WM_MENUSELECT:\r
-       {\r
-               statusBarTxt[0] = 0;                                    // Clear status bar text\r
-               uint16 flags = wParam >> 16;                    // Extract flags\r
-\r
-               if (!(flags & MFT_SEPARATOR))\r
-               {\r
-                       uint16 id = wParam & 0xFFFF;\r
-\r
-                       if (flags & MF_POPUP)\r
-                       {\r
-                               if (flags & MF_SYSMENU)\r
-                                       id = IDS_SYSMENU;\r
-                               else\r
-                                       id = IDM_FILEMENU + wParam;\r
-                       }\r
-\r
-                       LoadString(hInst, id, statusBarTxt, 64);\r
-               }\r
-\r
-               SendMessage(hStatusBar, SB_SETTEXT, 0 + SBT_NOBORDERS, (LPARAM)statusBarTxt);\r
-               break;\r
-       }\r
-       case WM_COMMAND:\r
-       {\r
-               uint16 cmd = wParam & 0xFFFF;\r
-\r
-               if (cmd == IDM_NEW)\r
-               {\r
-//                   call   CmdIDM_NEW\r
-               }\r
-               else if (cmd == IDM_OPEN)\r
-               {\r
-//                   call   SaveChanges\r
-//                   .IF (eax)\r
-//                     movmov ofn.hwndOwner, eax, hMainWnd\r
-//                     mov    ofn.Flags, OFN_PATHMUSTEXIST + OFN_FILEMUSTEXIST\r
-//                     invoke GetOpenFileName, ADDR ofn\r
-//                     .IF (eax)\r
-////////\r
-//jmp @F\r
-//szDMsg1a     BYTE    "Could not open the file (GetOpenFileName)...", 0\r
-//szDMsg1b     BYTE    "Open error!", 0\r
-//szDMsg1c     BYTE    "About to attempt to open file...", 0\r
-//@@:\r
-////invoke MessageBox, hWnd, ADDR szDMsg1a, ADDR szDMsg1b, MB_ICONERROR or MB_OK\r
-//invoke MessageBox, hMainWnd, ADDR szDMsg1c, ADDR szFile, MB_ICONERROR or MB_OK\r
-//                       invoke LoadTTF, ADDR szFile\r
-//\r
-//////\r
-//                       // <<< FILE OPEN CODE HERE >>>\r
-//                       or     fFileStatus, NAMEDbit\r
-//                       and    fFileStatus, NOT CHANGEDbit\r
-//                       call   NewWindowName\r
-//                       mov    eax, TRUE      // return TRUE\r
-//                       jmp    Return\r
-//                       //��������������������������������������\r
-//OpenError:             invoke GetLastError\r
-//                       // <<< FILE OPEN ERROR CODE HERE >>>\r
-//                     .ENDIF\r
-//                     zero   eax      // return FALSE\r
-//                   .ENDIF\r
-               }\r
-               else if (cmd == IDM_SAVEAS)\r
-               {\r
-//                   and    fFileStatus, NOT NAMEDbit\r
-//                   call   CmdIDM_SAVE\r
-               }\r
-               else if (cmd == IDM_SAVE)\r
-               {\r
-//                   call   CmdIDM_SAVE\r
-               }\r
-               else if (cmd == IDM_ABOUT)\r
-                       DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ABOUT), hMainWnd, AboutProc, NULL);\r
-               else if (cmd == IDM_EXIT)\r
-                       SendMessage(hWnd, WM_CLOSE, 0, 0);\r
-               else if (cmd == ID_TBCHARWIN)\r
-               {\r
-                       ShowWindow(hCharWnd, (IsWindowVisible(hCharWnd) ? SW_HIDE : SW_SHOWNOACTIVATE));\r
-\r
-#ifdef DEBUGFOO\r
-wpC.length = sizeof(WINDOWPLACEMENT);\r
-GetWindowPlacement(hCharWnd, &wpC);\r
-wsprintf(strBuf, "Char window showCmd = %08X...\n", wpC.showCmd);\r
-WriteLogMsg(strBuf);\r
-#endif\r
-               }\r
-               else\r
-                       return DefWindowProc(hWnd, msgID, wParam, lParam);\r
-\r
-               break;\r
-       }\r
-       default:\r
-               return DefWindowProc(hWnd, msgID, wParam, lParam);\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-//\r
-// Initialize TTF data\r
-//\r
-void CreateNewDoc(void)\r
-{\r
-}\r
-\r
-//\r
-// Save changes to document before quitting\r
-//\r
-bool SaveChanges(void)\r
-{\r
-       return true;\r
-}\r
-\r
-\r
-\r
-//\r
-// ABOUT Dialog WndProc\r
-//\r
-BOOL CALLBACK AboutProc(HWND hDlg, UINT msgID, WPARAM wParam, LPARAM lParam)\r
-{\r
-       switch (msgID)\r
-       {\r
-       case WM_INITDIALOG:\r
-\r
-               MiscCenterWnd(hDlg, hMainWnd);\r
-               break;\r
-\r
-       case WM_COMMAND:\r
-\r
-               if (wParam == IDOK || wParam == IDCANCEL)\r
-                       EndDialog(hDlg, TRUE);\r
-\r
-               break;\r
-\r
-       default:\r
-               return FALSE;\r
-       }\r
-\r
-       return TRUE;\r
-}\r
-\r
-//\r
-// Character Window WndProc\r
-//\r
-WndProcCW      PROC  STDCALL, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM\r
-\r
-               mov    eax, uMsg                // pickup our message\r
-               .IF (eax == WM_PAINT)\r
-                 mov    eax, 0                 // Non-sense... (placeholder!)\r
-// Scan conversion etc. goes here...\r
-               .ELSEIF (eax == WM_LBUTTONDOWN)\r
-                 invoke SetCapture, hCharWnd\r
-               .ELSEIF (eax == WM_LBUTTONUP)\r
-                 invoke ReleaseCapture\r
-                 invoke SetFocus, hMainWnd     // Make sure the main wnd keeps focus!\r
-               .ELSEIF (eax == WM_NCLBUTTONDOWN)\r
-                 invoke DefWindowProc, hWnd, uMsg, wParam, lParam // Let it do its thing\r
-                 invoke SetFocus, hMainWnd     // Make sure the main wnd keeps focus!\r
-               .ELSE\r
-DefProc:         invoke DefWindowProc, hWnd, uMsg, wParam, lParam\r
-               .ENDIF\r
-               ret\r
-\r
-WndProcCW      ENDP\r
-\r
-//\r
-// Character Window WndProc\r
-//\r
-LRESULT CALLBACK WndProcCW(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)\r
-{\r
-       switch (msgID)\r
-       {\r
-       default:\r
-               return DefWindowProc(hWnd, msgID, wParam, lParam);\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-\r
-// Function prototypes\r
-\r
-int32 FindSelectedTool(void);\r
-\r
-//\r
-// Tool Palette WndProc\r
-//\r
-LRESULT CALLBACK WndProcTP(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)\r
-{\r
-       PAINTSTRUCT ps;\r
-       HDC hdc;\r
-       POINT pt;\r
-       static uint32 prevTool = -1;\r
-\r
-       switch (msgID)\r
-       {\r
-       case WM_PAINT:\r
-       {\r
-               hdc = BeginPaint(hWnd, &ps);\r
-               HDC newDC = CreateCompatibleDC(NULL);\r
-               SelectObject(newDC, hBMToolPal1);\r
-               BitBlt(hdc, 0, 0, sizeTPBM.x, sizeTPBM.y, newDC, 0, 0, SRCCOPY);\r
-               DeleteDC(newDC);\r
-\r
-// This is crappy. Find some way to tighten this up!\r
-               int32 tool = FindSelectedTool();\r
-\r
-               if (tool != -1)\r
-               {\r
-                       newDC = CreateCompatibleDC(NULL);\r
-                       SelectObject(newDC, hBMToolPal1);\r
-                   //need ul corner of bitmap, ul corner of dest, width/height\r
-                       pt.x = sizeStamp.x * (tool & 0x03), pt.y = sizeStamp.y * (tool >> 2);\r
-                       BitBlt(hdc, pt.x, pt.y, sizeStamp.x, sizeStamp.y, newDC, pt.x, pt.y, NOTSRCCOPY);\r
-                       DeleteDC(newDC);\r
-               }\r
-\r
-               EndPaint(hWnd, &ps);\r
-               break;\r
-       }\r
-       case WM_MOUSEMOVE:\r
-       {\r
-               int32 tool = FindSelectedTool();\r
-\r
-               if (tool != prevTool)\r
-               {\r
-                       prevTool = tool;\r
-                       InvalidateRect(hWnd, NULL, FALSE);\r
-               }\r
-\r
-               break;\r
-       }\r
-       case WM_RBUTTONUP:\r
-       {\r
-               int32 tool = FindSelectedTool(), oldTool = currentTool;\r
-\r
-               if (tool != -1)\r
-                       currentTool = tool;\r
-\r
-               if (currentTool != TOOLSelect && currentTool != TOOLDelPt && currentTool != TOOLAddPt\r
-                       && currentTool != TOOLPolySelect)\r
-                       ptHighlight = -1;\r
-\r
-               if (currentTool != oldTool)\r
-                       InvalidateRect(hMainWnd, NULL, TRUE);\r
-\r
-               if (currentTool == TOOLAddPoly)\r
-#ifdef DEBUGFOO\r
-{\r
-#endif\r
-                       polyFirstPoint = true;\r
-#ifdef DEBUGFOO\r
-wsprintf(strBuf, "--> Selected poly tool, polyFirstPoint is %s\n", polyFirstPoint ? "true" : "false");\r
-WriteLogMsg(strBuf);\r
-}\r
-#endif\r
-\r
-               ReleaseCapture();\r
-               ShowWindow(hToolPalWnd, SW_HIDE);\r
-               SetFocus(hMainWnd);                                             // Make sure the main wnd keeps focus!\r
-\r
-               break;\r
-       }\r
-       default:\r
-               return DefWindowProc(hWnd, msgID, wParam, lParam);\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-//\r
-// Find which tool we're pointing at\r
-// Use: xcoord = mouse.x / (bmsize.x/4), ycoord = mouse.y / (bmsize.y/2)\r
-//\r
-int32 FindSelectedTool(void)\r
-{\r
-       POINT pt;\r
-               \r
-       GetCursorPos(&pt);\r
-       ScreenToClient(hToolPalWnd, &pt);\r
-\r
-       uint32 x = (uint32)pt.x / sizeStamp.x, y = (uint32)pt.y / sizeStamp.y, tool = -1;\r
-\r
-       if (x < 4 && y < 2)\r
-//     {\r
-               tool = (y * 4) + x;\r
-\r
-//             if (tool == 7)\r
-//                     tool = -1;                                                      // 7 has no tool...\r
-//     }\r
-\r
-       return tool;\r
-}\r
-\r
-\r
-//\r
-// Misc center window\r
-//\r
-void MiscCenterWnd(HWND hChild, HWND hParent)\r
-{\r
-       RECT parent, child;\r
-\r
-       if (!GetWindowRect(hParent, &parent) || !GetWindowRect(hChild, &child))\r
-               return;\r
-\r
-       int32 x = parent.left + (((parent.right - parent.left) - (child.right - child.left)) / 2),\r
-               y = parent.top + (((parent.bottom - parent.top) - (child.bottom - child.top)) / 2);\r
-\r
-       if (x < 0)\r
-               x = 0;\r
-       else if (x > GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left))\r
-               x = GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left);\r
-\r
-       if (y < 0)\r
-               y = 0;\r
-       else if (y > GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top))\r
-               y = GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top);\r
-\r
-       SetWindowPos(hChild, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\r
-}\r
-\r
-//\r
-// Allow only one instance\r
-//\r
-bool OnlyOneInstance(void)\r
-{\r
-       HWND window = FindWindow(className, NULL);\r
-\r
-       if (window == NULL)\r
-               return true;\r
-\r
-       ShowWindow(window, SW_SHOWNORMAL);\r
-       SetWindowPos(window, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);\r
-\r
-       return false;\r
-}\r
-\r
-//\r
-// Load/Allocate all resources\r
-//\r
-bool LoadResources(void)\r
-{\r
-       hCur[0] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR1));\r
-       hCur[1] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR2));\r
-       hCur[2] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR3));\r
-       hCur[3] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR4));\r
-       hCur[4] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR5));\r
-       hCur[5] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR6));\r
-       hCur[6] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR7));\r
-       hCur[7] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR8));\r
-\r
-       BITMAP bm;\r
-\r
-       hBMToolPal1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_TOOLPAL1));\r
-       GetObject(hBMToolPal1, sizeof(bm), &bm);\r
-\r
-       // Set up sizes\r
-\r
-       sizeTPBM.x = bm.bmWidth, sizeTPBM.y = bm.bmHeight;\r
-       sizeStamp.x = bm.bmWidth / 4, sizeStamp.y = bm.bmHeight / 2;\r
-\r
-       hBluePen1 = CreatePen(PS_DOT, 1, 0x00FF0000);\r
-       hRedPen1 = CreatePen(PS_SOLID, 1, 0x000000FF);\r
-       hGreenPen1 = CreatePen(PS_SOLID, 1, 0x0000AF00);\r
-       hBlackPen1 = CreatePen(PS_SOLID, 1, 0x00000000);\r
-\r
-       LOGBRUSH lb = { BS_NULL, 0, 0 };\r
-\r
-       hNullBrush = CreateBrushIndirect(&lb);\r
-\r
-       return true;\r
-}\r
-\r
-//\r
-// Deallocate all resources\r
-//\r
-void DeallocateResources(void)\r
-{\r
-       DeleteObject(hBMToolPal1);\r
-       DeleteObject(hBluePen1);\r
-       DeleteObject(hRedPen1);\r
-       DeleteObject(hGreenPen1);\r
-       DeleteObject(hBlackPen1);\r
-       DeleteObject(hNullBrush);\r
-}\r
-\r
-//\r
-// Save all application specific data, so we can pick up where we last left off...\r
-//\r
-void SaveAppState(void)\r
-{\r
-       SetINIInt("Main", "flags", wpM.flags);\r
-       SetINIInt("Main", "showCmd", wpM.showCmd);\r
-       SetINIInt("Main", "x1", wpM.rcNormalPosition.left);\r
-       SetINIInt("Main", "y1", wpM.rcNormalPosition.top);\r
-       SetINIInt("Main", "x2", wpM.rcNormalPosition.right);\r
-       SetINIInt("Main", "y2", wpM.rcNormalPosition.bottom);\r
-\r
-       SetINIInt("Main", "vpx", ptVPM.x);\r
-       SetINIInt("Main", "vpy", ptVPM.y);\r
-\r
-       SetINIInt("Char", "flags", wpC.flags);\r
-       SetINIInt("Char", "showCmd", wpC.showCmd);\r
-       SetINIInt("Char", "x1", wpC.rcNormalPosition.left);\r
-       SetINIInt("Char", "y1", wpC.rcNormalPosition.top);\r
-       SetINIInt("Char", "x2", wpC.rcNormalPosition.right);\r
-       SetINIInt("Char", "y2", wpC.rcNormalPosition.bottom);\r
-\r
-       // Need to write out currently opened font, character looking at, other misc. crap\r
-//     SetINIString("Main", "currentFile", pDoc->GetPathName());\r
-//     SetINIInt("Main", "currentChar", pDoc->character_num);\r
-}\r
-\r
-//\r
-// Restore all application specific data previously saved\r
-//\r
-bool RestoreAppState(void)\r
-{\r
-       InitINIFile();\r
-\r
-       WINDOWPLACEMENT wp;\r
-       wp.length = sizeof(WINDOWPLACEMENT);\r
-       GetWindowPlacement(hMainWnd, &wp);\r
-\r
-       wp.flags = GetINIInt("Main", "flags", wp.flags);\r
-       wp.showCmd = GetINIInt("Main", "showCmd", wp.showCmd);\r
-       wp.rcNormalPosition.left = GetINIInt("Main", "x1", wp.rcNormalPosition.left);\r
-       wp.rcNormalPosition.top = GetINIInt("Main", "y1", wp.rcNormalPosition.top);\r
-       wp.rcNormalPosition.right = GetINIInt("Main", "x2", wp.rcNormalPosition.right);\r
-       wp.rcNormalPosition.bottom = GetINIInt("Main", "y2", wp.rcNormalPosition.bottom);\r
-\r
-       SetWindowPlacement(hMainWnd, &wp);\r
-\r
-       HDC hdc;\r
-       POINT pt;\r
-       hdc = GetDC(hMainWnd);\r
-       GetViewportOrgEx(hdc, &pt);\r
-\r
-       pt.x = GetINIInt("Main", "vpx", pt.x);\r
-       pt.y = GetINIInt("Main", "vpy", pt.y);\r
-\r
-       SetViewportOrgEx(hdc, pt.x, pt.y, NULL);\r
-       ReleaseDC(hMainWnd, hdc);\r
-\r
-       GetWindowPlacement(hCharWnd, &wp);\r
-\r
-       wp.flags = GetINIInt("Char", "flags", wp.flags);\r
-       wp.showCmd = GetINIInt("Char", "showCmd", wp.showCmd);\r
-       wp.rcNormalPosition.left = GetINIInt("Char", "x1", wp.rcNormalPosition.left);\r
-       wp.rcNormalPosition.top = GetINIInt("Char", "y1", wp.rcNormalPosition.top);\r
-       wp.rcNormalPosition.right = GetINIInt("Char", "x2", wp.rcNormalPosition.right);\r
-       wp.rcNormalPosition.bottom = GetINIInt("Char", "y2", wp.rcNormalPosition.bottom);\r
-\r
-       SetWindowPlacement(hCharWnd, &wp);\r
-\r
-       if (wp.showCmd == SW_HIDE)\r
-               SendMessage(hToolBar, TB_SETSTATE, ID_TBCHARWIN, MAKELONG(TBSTATE_ENABLED, 0));\r
-\r
-//  CString lastFile = theApplicationObject.GetProfileString(version, "currentFile", "");\r
-//  int lastChar = theApplicationObject.GetProfileInt(version, "currentChar", 0);\r
-//  if (lastFile.GetLength())\r
-//  {\r
-//    // Attempt to restore the last session by open the last file used, etc...\r
-//    if (!pDoc->m_myFont.Load(lastFile))\r
-//    {\r
-//      // Err, make sure you can support any allegations you make below, buddy!\r
-//      AfxMessageBox("The last file opened with TTF Edit\n\rseems to have been moved or deleted.");\r
-//    }\r
-//    else\r
-//    {\r
-//      pDoc->m_myFont.SetGlyph(lastChar);  // Set TTF object to last used char\r
-//      pDoc->character_num = lastChar;\r
-//      pDoc->SetPathName(lastFile);\r
-//\r
-//      BYTE name[512];\r
-//      pDoc->m_myFont.GetCharName(lastChar, name);\r
-//      m_wndOwned.SetWindowText((char *)name);\r
-//    }\r
-//  }\r
-\r
-       return true;\r
-}\r
-\r
-//\r
-// Initialization\r
-//\r
-bool Initialization(void)\r
-{\r
-       WNDCLASSEX wcex;\r
-\r
-       if (!LoadResources())\r
-               return false;\r
-\r
-       RtlFillMemory(&wcex, sizeof(WNDCLASSEX), 0);\r
-       wcex.cbSize = sizeof(WNDCLASSEX);\r
-       wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;\r
-       wcex.lpfnWndProc = WndProc;\r
-       wcex.hInstance = hInst;\r
-       wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON));\r
-       wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);\r
-       wcex.lpszMenuName = MAKEINTRESOURCE(IDM_MENU);\r
-       wcex.lpszClassName = className;\r
-       wcex.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, NULL);\r
-\r
-       if (!RegisterClassEx(&wcex))\r
-               return false;\r
-\r
-       hMainWnd = CreateWindowEx(NULL, className, className, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,\r
-               0, 0, 0x1A0, 0x180, NULL, NULL, hInst, NULL);\r
-\r
-       if (!hMainWnd)\r
-               return false;\r
-\r
-       ShowWindow(hMainWnd, nCmdShow);\r
-       UpdateWindow(hMainWnd);\r
-\r
-       // Character window creation\r
-\r
-       wcex.lpfnWndProc = WndProcCW;\r
-       wcex.lpszMenuName = NULL;\r
-       wcex.lpszClassName = CNCharWin;\r
-       wcex.hCursor = LoadCursor(NULL, IDC_ARROW);     // Owned windows have "regular" cursors\r
-\r
-       if (!RegisterClassEx(&wcex))\r
-               return false;\r
-\r
-       hCharWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW, CNCharWin,\r
-               curCharName, WS_POPUP | WS_CAPTION | WS_VISIBLE | WS_THICKFRAME,\r
-               100, 100, 120, 120, hMainWnd, NULL, hInst, NULL);\r
-\r
-       if (!hCharWnd)\r
-               return false;\r
-\r
-       ShowWindow(hCharWnd, SW_SHOWNORMAL);\r
-       UpdateWindow(hCharWnd);\r
-       SetFocus(hMainWnd);                                                     // Make sure main wnd has focus!\r
-\r
-       // Tool palette window creation\r
-\r
-       wcex.lpfnWndProc = WndProcTP;\r
-       wcex.lpszClassName = CNToolPal;\r
-\r
-       if (!RegisterClassEx(&wcex))\r
-               return false;\r
-\r
-       hToolPalWnd = CreateWindowEx(WS_EX_WINDOWEDGE, CNToolPal, NULL, WS_POPUP,\r
-               0, 0, sizeTPBM.x, sizeTPBM.y, hMainWnd, NULL, hInst, NULL);\r
-\r
-       if (!hToolPalWnd)\r
-               return false;\r
-\r
-// Note: A better way to handle this would be to have a sub that registers ALL\r
-//       classes beforehand and passes a TRUE/FALSE back depending on whether or not\r
-//       all the classes were able to be registered or not, THEN create the windows\r
-//       and controls...\r
-\r
-       RestoreAppState();                                                      // Restore app related stuff\r
-\r
-       return true;\r
-}\r
-\r
-#endif\r
+//
+// TTEDIT.CPP - The TrueType Editor
+// by James L. Hammons
+// (C) 2004 Underground Software
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  08/28/2008  Created this file
+//
+
+// FIXED:
+//
+// STILL TO BE DONE:
+//
+// - Fix bug in Glyphpoints when dragging on an empty canvas or loading a font
+// - Fix scrolling, zooming, settings (ini)
+//
+
+// Uncomment this for debugging...
+#define DEBUG
+#define DEBUGFOO            // Various tool debugging...
+#define DEBUGTP                                // Toolpalette debugging...
+
+#include "editwindow.h"
+#include "graphicprimitives.h"
+#include "toolwindow.h"
+#include "debug.h"
+#include "vector.h"
+
+
+BEGIN_EVENT_TABLE(TTEditWindow, wxWindow)
+       EVT_PAINT(TTEditWindow::OnPaint)
+       EVT_MOUSE_EVENTS(TTEditWindow::OnMouseEvent)
+END_EVENT_TABLE()
+
+TTEditWindow::TTEditWindow(wxFrame * parent, const wxPoint &pos, const wxSize &size, long style):
+       wxWindow(parent, -1, pos, size, style | wxFULL_REPAINT_ON_RESIZE),
+       app(wxGetApp()), scale(1.0), offsetX(-10), offsetY(-10), tool(TOOLSelect),
+       ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1), oldPtNextHighlight(-1),
+       polyFirstPoint(true), bmp(NULL)
+{ 
+       SetCursor(*(app.cur[tool]));
+       SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF));
+
+       wxString s;
+       s.Printf(_("Zoom: %.2f%%"), scale * 100.0);
+       parent->SetStatusText(s, 1);
+}
+
+TTEditWindow::~TTEditWindow(void)
+{
+       if (bmp)
+               delete bmp;
+}
+
+void TTEditWindow::OnPaint(wxPaintEvent &e)
+{
+       wxPaintDC dc(this);
+//Doesn't do crap!
+//dc.SetBackground(*wxWHITE_BRUSH);
+
+// Due to the screwiness of wxWidgets coord system, the origin is ALWAYS
+// the upper left corner--regardless of axis orientation, etc...
+       wxCoord width, height;
+       dc.GetSize(&width, &height);
+
+       dc.SetDeviceOrigin(-offsetX, height - (-offsetY));
+       dc.SetAxisOrientation(true, true);
+
+// Scrolling can be done by using OffsetViewportOrgEx
+// Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform)
+// you'd use: % = ViewportExt / WindowExt
+// But it makes the window look like crap: fuggetuboutit.
+// Instead, we have to scale EVERYTHING by hand. Crap!
+// It's not *that* bad, but not as convenient either...
+
+       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0xFF), 1, wxDOT)));
+//     dc.DrawLine(0, 0, 10, 10);
+
+    // Draw coordinate axes
+
+       dc.CrossHair(0, 0);
+
+    // Draw points
+
+       for(int i=0; i<pts.GetNumPoints(); i++)
+       {
+               if (i == ptHighlight)
+               {
+                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));
+//                     SelectObject(hdc, hRedPen1);
+
+                       if (pts.GetOnCurve(i))
+                       {
+                               DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7);
+                               DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9);
+                       }
+                       else
+                       {
+                               DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7);
+                               DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 9);
+                       }
+               }
+               else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt)
+               {
+                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0xAF, 0x00), 1, wxSOLID)));
+//                     SelectObject(hdc, hGreenPen1);
+
+                       if (pts.GetOnCurve(i))
+                       {
+                               DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7);
+                               DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9);
+                       }
+                       else
+                       {
+                               DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7);
+                               DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 9);
+                       }
+               }
+               else
+               {
+                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));
+//                     SelectObject(hdc, hBlackPen1);
+
+                       if (pts.GetOnCurve(i))
+                               DrawSquareDot(dc, pts.GetX(i), pts.GetY(i));
+                       else
+                               DrawRoundDot(dc, pts.GetX(i), pts.GetY(i));
+               }
+
+               if (tool == TOOLDelPt && i == ptHighlight)
+               {
+                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));
+//                     SelectObject(hdc, hRedPen1);
+//                     MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL);
+//                     LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5);
+//                     LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness!
+//                     MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL);
+//                     LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5);
+//                     LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!!
+                       dc.DrawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5);
+                       dc.DrawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5);
+               }
+       }
+
+//             SelectObject(hdc, hBlackPen1);
+       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));
+
+       // Draw curve formed by points
+
+       for(int poly=0; poly<pts.GetNumPolys(); poly++)
+       {
+               if (pts.GetNumPoints(poly) > 2)
+               {
+                       // Initial move...
+                       // If it's not on curve, then move to it, otherwise move to last point...
+
+                       wxCoord x, y;
+       
+                       if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1))
+                               x = (wxCoord)pts.GetX(poly, pts.GetNumPoints(poly) - 1), y = (wxCoord)pts.GetY(poly, pts.GetNumPoints(poly) - 1);
+                       else
+                               x = (wxCoord)pts.GetX(poly, 0), y = (wxCoord)pts.GetY(poly, 0);
+       
+                       for(int i=0; i<pts.GetNumPoints(poly); i++)
+                       {
+                               if (pts.GetOnCurve(poly, i))
+//                                     LineTo(hdc, pts.GetX(poly, i), pts.GetY(poly, i));
+                               {
+                                       dc.DrawLine(x, y, pts.GetX(poly, i), pts.GetY(poly, i));
+                                       x = (wxCoord)pts.GetX(poly, i), y = (wxCoord)pts.GetY(poly, i);
+                               }
+                               else
+                               {
+                                       uint32 prev = pts.GetPrev(poly, i), next = pts.GetNext(poly, i);
+                                       float px = pts.GetX(poly, prev), py = pts.GetY(poly, prev),
+                                               nx = pts.GetX(poly, next), ny = pts.GetY(poly, next);
+       
+                                       if (!pts.GetOnCurve(poly, prev))
+                                               px = (px + pts.GetX(poly, i)) / 2.0f,
+                                               py = (py + pts.GetY(poly, i)) / 2.0f;
+       
+                                       if (!pts.GetOnCurve(poly, next))
+                                               nx = (nx + pts.GetX(poly, i)) / 2.0f,
+                                               ny = (ny + pts.GetY(poly, i)) / 2.0f;
+       
+                                       Bezier(dc, point(px, py), point(pts.GetX(poly, i), pts.GetY(poly, i)), point(nx, ny));
+                                       x = (wxCoord)nx, y = (wxCoord)ny;
+       
+                                       if (pts.GetOnCurve(poly, next))
+                                               i++;                                    // Following point is on curve, so move past it
+                               }
+                       }
+               }
+       }
+
+//             SelectObject(hdc, oldPen);                              // Restore the stuff we disrupted...
+       dc.SetPen(wxNullPen);
+//             SelectObject(hdc, oldBrush);
+//             EndPaint(hWnd, &ps);
+}
+
+void TTEditWindow::OnMouseEvent(wxMouseEvent &e)
+{
+#ifdef DEBUGTP
+//printf("!!! This window %s focus...!\n", (HasCapture() ? "has" : "doesn't have"));
+#endif
+       if (e.RightDown())
+       {
+               // Handle tool palette (NOTE: tool palette deals with RightUp event.)
+
+               wxPoint pt = ClientToScreen(e.GetPosition());
+               app.toolPalette->Move(pt);
+               app.toolPalette->Show(true);
+               SetCursor(*wxSTANDARD_CURSOR);
+               app.toolPalette->SetCursor(*wxSTANDARD_CURSOR);
+               app.toolPalette->prevTool = TOOLSelect;
+               app.toolPalette->Refresh(false);
+               CaptureMouse();
+       }
+       else if (e.RightUp())
+       {
+               ToolType newTool = app.toolPalette->FindSelectedTool();//, oldTool = tool;
+
+               // We only change the tool if a new one was actually selected. Otherwise, we do nothing.
+               if (newTool != TOOLNone)
+               {
+                       tool = newTool;
+
+                       if (tool == TOOLScroll || tool == TOOLZoom || tool == TOOLAddPoly
+                               || tool == TOOLDelPoly)
+                               ptHighlight = -1;
+
+                       if (tool == TOOLAddPoly)
+                               polyFirstPoint = true;
+               }
+
+               ReleaseMouse();
+               app.toolPalette->Show(false);
+               SetCursor(*(app.cur[tool]));
+       }
+       else if (e.LeftDown())
+       {
+               if (tool == TOOLScroll || tool == TOOLZoom)
+                       CaptureMouse();                                         // Make sure we capture the mouse when in scroll/zoom mode
+               else if (tool == TOOLAddPt)             // "Add Point" tool
+               {
+                       if (pts.GetNumPoints() > 0)
+                       {
+                               wxPoint pt = GetAdjustedMousePosition(e);
+                               pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (e.ShiftDown() | e.ControlDown() ? false : true));
+                               ptHighlight = ptNextHighlight;
+                               Refresh();
+                       }
+               }
+               else if (tool == TOOLAddPoly)   // "Add Poly" tool
+               {
+#ifdef DEBUGFOO
+WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints());
+#endif
+                       if (polyFirstPoint)
+                       {
+                               polyFirstPoint = false;
+                               pts.AddNewPolyAtEnd();
+                       }
+
+                       wxPoint pt = GetAdjustedMousePosition(e);
+                       // Append a point to the end of the structure
+                       pts += IPoint(pt.x, pt.y, (e.ShiftDown() | e.ControlDown() ? false : true));
+                       ptHighlight = pts.GetNumPoints() - 1;
+                       Refresh();
+#ifdef DEBUGFOO
+WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumPoints());
+#endif
+               }
+               else if (tool == TOOLSelect || tool == TOOLPolySelect)
+               {
+                       if (pts.GetNumPoints() > 0)
+                       {
+                               pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                               WarpPointer(pt.x, pt.y);
+
+                               if (e.ShiftDown() | e.ControlDown())
+                                       pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight));
+                       }
+               }
+               else if (tool == TOOLDelPt)
+               {
+                       if (pts.GetNumPoints() > 0)
+//Or could use:
+//                     if (ptHighlight != -1)
+                       {
+//This assumes that WM_MOUSEMOVE happens before this!
+//The above commented out line should take care of this contingency... !!! FIX !!!
+                               pts.DeletePoint(ptHighlight);
+                               Refresh();
+                       }
+               }
+       }
+       else if (e.LeftUp())
+       {
+//             mouseDown = false;
+
+               if (tool == TOOLScroll || tool == TOOLZoom)
+                       ReleaseMouse();
+       }
+       else if (e.Dragging())
+       {
+               if (e.RightIsDown())
+               {
+                       ToolType newTool = app.toolPalette->FindSelectedTool();
+
+                       if (newTool != app.toolPalette->prevTool)
+                       {
+                               app.toolPalette->prevTool = newTool;
+                               app.toolPalette->Refresh(false);
+                       }
+
+                       return;
+               }
+
+               if (e.MiddleIsDown())
+               {
+                   // Calc offset from previous point
+                       pt = e.GetPosition();
+                       ptOffset.x = pt.x - ptPrevious.x,
+                       ptOffset.y = pt.y - ptPrevious.y;
+
+// Then multiply it by the scaling factor. Whee!
+                       // This looks wacky because we're using screen coords for the offset...
+                       // Otherwise, we would subtract both offsets!
+                       offsetX -= ptOffset.x, offsetY += ptOffset.y;
+                       Refresh();
+
+                       return;
+               }
+
+//             if (e.LeftIsDown())
+//             {
+#if 0
+                       if (tool == TOOLScroll)
+                       {
+                           // Extract current point from lParam/calc offset from previous point
+
+                               pt = e.GetPosition();
+                               ptOffset.x = pt.x - ptPrevious.x,
+                               ptOffset.y = pt.y - ptPrevious.y;
+
+                               // NOTE: OffsetViewportOrg operates in DEVICE UNITS...
+
+//Seems there's no equivalent for this in wxWidgets...!
+//!!! FIX !!!
+//                             hdc = GetDC(hWnd);
+//                             OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL);
+//                             ReleaseDC(hWnd, hdc);
+
+// this shows that it works, so the logic above must be faulty...
+// And it is. It should convert the coords first, then do the subtraction to figure the offset...
+// Above: DONE
+// Then multiply it by the scaling factor. Whee!
+                               // This looks wacky because we're using screen coords for the offset...
+                               // Otherwise, we would subtract both offsets!
+                               offsetX -= ptOffset.x, offsetY += ptOffset.y;
+                               Refresh();
+                       }
+                       else
+#endif
+ if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect)
+                       {
+                               if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch.
+                               {
+//temporary, for testing. BTW, Select drag bug is here...!
+#if 0
+                                       wxPoint pt2 = GetAdjustedMousePosition(e);
+                                       pts.SetXY(ptHighlight, pt2.x, pt2.y);
+                                       Refresh();
+#endif
+                               }
+                       }
+                       else if (tool == TOOLPolySelect)
+                       {
+                               if (pts.GetNumPoints() > 0)
+                               {
+                                       wxPoint pt2 = GetAdjustedMousePosition(e);
+                                       // Should also set onCurve here as well, depending on keystate
+//Or should we?
+                                       pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight));
+                                       Refresh();
+                               }
+                       }
+//             }
+
+               ptPrevious = pt;
+       }
+       else if (e.Moving())
+       {
+//             else    // Moving, not dragging...
+//             {
+                       if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt
+                               || tool == TOOLPolySelect)// || tool == TOOLAddPoly)
+                       {
+                               wxPoint pt2 = GetAdjustedMousePosition(e);
+                               double closest = 1.0e+99;
+
+                               for(int i=0; i<pts.GetNumPoints(); i++)
+                               {
+                                       double dist = ((pt2.x - pts.GetX(i)) * (pt2.x - pts.GetX(i)))
+                                               + ((pt2.y - pts.GetY(i)) * (pt2.y - pts.GetY(i)));
+
+                                       if (dist < closest)
+                                               closest = dist, ptHighlight = i;
+                               }
+
+                               if (ptHighlight != oldPtHighlight)
+                               {
+                                       oldPtHighlight = ptHighlight;
+                                       Refresh();
+                               }
+
+                               // What follows here looks like voodoo, but is really simple. What we do is
+                               // check to see if the mouse point has a perpendicular intersection with any of
+                               // the line segments. If it does, calculate the length of the perpendicular
+                               // and choose the smallest length. If there is no perpendicular, then choose the
+                               // length of line connecting the closer of either the first endpoint or the
+                               // second and choose the smallest of those.
+
+                               // There is one bit of math that looks like voodoo to me ATM--will explain once
+                               // I understand it better (the calculation of the length of the perpendicular).
+
+                               if (pts.GetNumPoints() > 1 && tool == TOOLAddPt)
+                               {
+                                       double smallest = 1.0e+99;
+
+                                       for(int i=0; i<pts.GetNumPoints(); i++)
+                                       {
+                                               int32 p1x = pts.GetX(i), p1y = pts.GetY(i),
+                                                       p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i));
+
+                                               vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x, pt2.y, 0, p1x, p1y, 0),
+                                                       v2(pt2.x, pt2.y, 0, p2x, p2y, 0);
+                                               double pp = ls.dot(v1) / ls.length(), dist;
+// Geometric interpretation:
+// pp is the paremeterized point on the vector ls where the perpendicular intersects ls.
+// If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls,
+// then the perpendicular lies beyond the 2nd endpoint.
+
+                                               if (pp < 0.0)
+                                                       dist = v1.length();
+                                               else if (pp > ls.length())
+                                                       dist = v2.length();
+                                               else                                    // distance = ?Det?(ls, v1) / |ls|
+                                                       dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.length());
+
+//The answer to the above looks like it might be found here:
+//
+//If the segment endpoints are s and e, and the point is p, then the test for the perpendicular
+//intercepting the segment is equivalent to insisting that the two dot products {s-e}.{s-p} and
+//{e-s}.{e-p} are both non-negative.  Perpendicular distance from the point to the segment is
+//computed by first computing the area of the triangle the three points form, then dividing by the
+//length of the segment.  Distances are done just by the Pythagorean theorem.  Twice the area of the
+//triangle formed by three points is the determinant of the following matrix:
+//
+//sx sy 1
+//ex ey 1
+//px py 1
+//
+//(???) By translating the start point to the origin, this can be rewritten as:
+//By subtracting row 1 from all rows, you get the following:
+//
+//0         0         0
+//(ex - sx) (ey - sy) 0
+//(px - sx) (py - sy) 0
+//
+//which greatly simplifies the calculation of the determinant.
+
+                                               if (dist < smallest)
+                                                       smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i;
+                                       }
+
+                                       if (ptNextHighlight != oldPtNextHighlight)
+                                       {
+                                               oldPtNextHighlight = ptNextHighlight;
+                                               Refresh();
+                                       }
+                               }
+                       }
+//             }
+
+               ptPrevious = e.GetPosition();
+       }
+}
+
+wxPoint TTEditWindow::GetAdjustedMousePosition(wxMouseEvent &e)
+{
+       wxCoord width, height;
+       wxClientDC dc(this);
+
+       dc.GetSize(&width, &height);
+       dc.SetDeviceOrigin(-offsetX, height - (-offsetY));
+       dc.SetAxisOrientation(true, true);
+
+#if 0
+wxStatusBar * sb = ((wxFrame *)GetParent())->GetStatusBar();
+wxString s;
+s.Printf("Logical mouse pos: %d, %d (%d, %d)", pt.x, pt.y, width, height);
+sb->SetStatusText(s);
+#endif
+
+       return e.GetLogicalPosition(dc);
+}
+
+wxPoint TTEditWindow::GetAdjustedClientPosition(wxCoord x, wxCoord y)
+{
+       wxCoord width, height;
+       wxClientDC dc(this);
+
+       dc.GetSize(&width, &height);
+       dc.SetDeviceOrigin(-offsetX, height - (-offsetY));
+       dc.SetAxisOrientation(true, true);
+
+       return wxPoint(dc.LogicalToDeviceX(x), dc.LogicalToDeviceY(y));
+}
+
+
+#if 0
+
+!!! OLD STUFF !!!
+
+
+LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
+{
+       RECT rc1, rc2;
+       HDC hdc;
+       POINT pt, ptOffset;
+       SIZE sz;
+       PAINTSTRUCT ps;
+
+       switch (msgID)
+       {
+       case WM_CREATE:
+
+               MiscCenterWnd(hWnd, GetDesktopWindow());
+               InitCommonControls();
+               hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, statusBarTxt, hWnd, ID_STATUSBAR);
+
+               if (!hStatusBar)
+                       return -1;
+
+// clean this crap up!
+// well, the only crappy thing here is using a POINT as an int array, but otherwise, this is OK
+               wsprintf(strBuf, zoom, 1000);
+               hdc = GetDC(hWnd);
+               GetTextExtentPoint32(hdc, strBuf, lstrlen(strBuf), &sz);
+               ReleaseDC(hWnd, hdc);
+               zoomWndWidth = sz.cx;
+               wsprintf(strBuf, zoom, 100);
+
+               GetClientRect(hWnd, &rc1);
+               pt.x = rc1.right - zoomWndWidth, pt.y = -1;
+               SendMessage(hStatusBar, SB_SETPARTS, 2, (LPARAM)&pt);
+               SendMessage(hStatusBar, SB_SETTEXT, (0 | SBT_NOBORDERS), (LPARAM)statusBarTxt);
+               SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM)strBuf);
+
+               hToolBar = CreateToolbarEx(hWnd, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS,
+                       IDR_TOOLBAR1, 3, hInst, IDB_TOOLBAR1, tbButtons, 4, 16, 16, 16, 16, sizeof(TBBUTTON));
+
+               if (!hToolBar)
+                       return -1;
+
+               CreateNewDoc();
+
+// The following can only be done because we use a private DC (using "CS_OWNDC")
+// (Is that true???)
+// Set the mapping to draw the character so it fits in the viewport...
+               hdc = GetDC(hWnd);
+               GetClientRect(hWnd, &rc1);
+               GetClientRect(hStatusBar, &rc2);
+               rc1.bottom -= rc2.bottom;
+               SetMapMode(hdc, MM_ISOTROPIC);
+               SetWindowExtEx(hdc, rc1.right, rc1.bottom, NULL);
+               SetViewportExtEx(hdc, rc1.right, -rc1.bottom, NULL);
+               SetViewportOrgEx(hdc, 0, rc1.bottom, NULL);
+               ReleaseDC(hWnd, hdc);
+               break;
+
+       case WM_CLOSE:
+
+               if (SaveChanges())
+               {
+                       wpM.length = wpC.length = sizeof(WINDOWPLACEMENT);
+                       GetWindowPlacement(hMainWnd, &wpM);
+                       GetWindowPlacement(hCharWnd, &wpC);
+
+                       if (!IsWindowVisible(hCharWnd))         // Needed because Windows lies about visibility
+                               wpC.showCmd = SW_HIDE;
+
+                       hdc = GetDC(hWnd);
+                       GetViewportOrgEx(hdc, &ptVPM);
+                       ReleaseDC(hWnd, hdc);
+
+                       DestroyWindow(hWnd);
+               }
+
+               break;
+
+       case WM_DESTROY:
+
+               PostQuitMessage(0);
+               break;
+
+       case WM_NCLBUTTONDOWN:
+
+               if (wParam == HTCAPTION)
+               {
+                       NCMouseDown = true;
+                       GetWindowRect(hMainWnd, &rc1);
+                       GetWindowRect(hCharWnd, &rc2);
+                       ptWinOffset.x = rc2.left - rc1.left;
+                       ptWinOffset.y = rc2.top - rc1.top;
+               }
+                   
+               // Let Windows do its thing with this msg, or weird things will happen...
+
+               DefWindowProc(hWnd, msgID, wParam, lParam);
+               NCMouseDown = false;
+               break;
+
+       case WM_WINDOWPOSCHANGING:
+
+               if (NCMouseDown)
+               {
+                       WINDOWPOS * wp = (WINDOWPOS *)lParam;
+
+                       if (wp->hwnd == hMainWnd && !(wp->flags & SWP_NOMOVE))
+                               SetWindowPos(hCharWnd, 0, wp->x + ptWinOffset.x, wp->y + ptWinOffset.y,
+                                               0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+               }
+
+               return DefWindowProc(hWnd, msgID, wParam, lParam);      // Seems this is needed... Bleah!
+
+       case WM_PAINT:
+       {
+               hdc = BeginPaint(hWnd, &ps);
+
+// Scrolling can be done by using OffsetViewportOrgEx
+// Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform)
+// you'd use: % = ViewportExt / WindowExt
+// But it makes the window look like crap: fuggetuboutit.
+// Instead, we have to scale EVERYTHING by hand. Crap!
+
+               // Apparently, you *must* save the individual object types (pen, brush, etc.)
+
+               HGDIOBJ oldPen = SelectObject(hdc, hBluePen1),
+                       oldBrush = SelectObject(hdc, hNullBrush);
+
+           // Draw coordinate axes
+
+               MoveToEx(hdc, 0, -32000, NULL);
+               LineTo(hdc, 0, 32000);
+               MoveToEx(hdc, -32000, 0, NULL);
+               LineTo(hdc, 32000, 0);
+
+           // Draw points
+
+               for(int i=0; i<pts.GetNumPoints(); i++)
+               {
+                       if (i == ptHighlight)
+                       {
+                               SelectObject(hdc, hRedPen1);
+
+                               if (pts.GetOnCurve(i))
+                               {
+                                       DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 7);
+                                       DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 9);
+                               }
+                               else
+                               {
+                                       DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 7);
+                                       DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 9);
+                               }
+                       }
+                       else if ((i == ptHighlight || i == ptNextHighlight) && currentTool == TOOLAddPt)
+                       {
+                               SelectObject(hdc, hGreenPen1);
+
+                               if (pts.GetOnCurve(i))
+                               {
+                                       DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 7);
+                                       DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 9);
+                               }
+                               else
+                               {
+                                       DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 7);
+                                       DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 9);
+                               }
+                       }
+                       else
+                       {
+                               SelectObject(hdc, hBlackPen1);
+
+                               if (pts.GetOnCurve(i))
+                                       DrawSquareDot(hdc, pts.GetX(i), pts.GetY(i));
+                               else
+                                       DrawRoundDot(hdc, pts.GetX(i), pts.GetY(i));
+                       }
+
+                       if (currentTool == TOOLDelPt && i == ptHighlight)
+                       {
+                               SelectObject(hdc, hRedPen1);
+                               MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL);
+                               LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5);
+                               LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness!
+                               MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL);
+                               LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5);
+                               LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!!
+                       }
+               }
+
+               SelectObject(hdc, hBlackPen1);
+
+               // Draw curve formed by points
+
+               for(int poly=0; poly<pts.GetNumPolys(); poly++)
+               {
+                       if (pts.GetNumPoints(poly) > 2)
+                       {
+                               // Initial move...
+                               // If it's not on curve, then move to it, otherwise move to last point...
+       
+                               if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1))
+                                       MoveToEx(hdc, pts.GetX(poly, pts.GetNumPoints(poly) - 1), pts.GetY(poly, pts.GetNumPoints(poly) - 1), NULL);
+                               else
+                                       MoveToEx(hdc, pts.GetX(poly, 0), pts.GetY(poly, 0), NULL);
+       
+                               for(int i=0; i<pts.GetNumPoints(poly); i++)
+                               {
+                                       if (pts.GetOnCurve(poly, i))
+                                               LineTo(hdc, pts.GetX(poly, i), pts.GetY(poly, i));
+                                       else
+                                       {
+                                               uint32 prev = pts.GetPrev(poly, i), next = pts.GetNext(poly, i);
+                                               float px = pts.GetX(poly, prev), py = pts.GetY(poly, prev),
+                                                       nx = pts.GetX(poly, next), ny = pts.GetY(poly, next);
+       
+                                               if (!pts.GetOnCurve(poly, prev))
+                                                       px = (px + pts.GetX(poly, i)) / 2.0f,
+                                                       py = (py + pts.GetY(poly, i)) / 2.0f;
+       
+                                               if (!pts.GetOnCurve(poly, next))
+                                                       nx = (nx + pts.GetX(poly, i)) / 2.0f,
+                                                       ny = (ny + pts.GetY(poly, i)) / 2.0f;
+       
+                                               Bezier(hdc, point(px, py), point(pts.GetX(poly, i), pts.GetY(poly, i)), point(nx, ny));
+       
+                                               if (pts.GetOnCurve(poly, next))
+                                                       i++;                                    // Following point is on curve, so move past it
+                                       }
+                               }
+                       }
+               }
+
+               SelectObject(hdc, oldPen);                              // Restore the stuff we disrupted...
+               SelectObject(hdc, oldBrush);
+               EndPaint(hWnd, &ps);
+               break;
+       }
+       case WM_SIZE:
+
+               // Apparently this is needed since these windows don't update themselves.
+               SendMessage(hStatusBar, msgID, wParam, lParam);
+               SendMessage(hToolBar, msgID, wParam, lParam);
+
+               // This is needed to make the 2nd status pane visible
+               GetClientRect(hWnd, &rc1);
+               pt.x = rc1.right - zoomWndWidth, pt.y = -1;
+               SendMessage(hStatusBar, SB_SETPARTS, 2, (LPARAM)&pt);
+               break;
+
+       case WM_RBUTTONDOWN:
+
+               GetCursorPos(&pt);
+               SetWindowPos(hToolPalWnd, 0, pt.x, pt.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
+               SetFocus(hToolPalWnd);
+               SetCapture(hToolPalWnd);                                // Ensure tool palette gets RButtonUp
+               SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));        // Tool pallete has "regular" cursor
+               break;
+
+       case WM_LBUTTONDOWN:
+
+               mouseDown = true;
+
+               if (currentTool == TOOLScroll || currentTool == TOOLZoom)
+                       SetCapture(hWnd);                                       // Make sure we capture the mouse when in scroll/zoom mode
+               else if (currentTool == TOOLAddPt)              // "Add Point" tool
+               {
+                       if (pts.GetNumPoints() > 0)
+                       {
+//Do we really need to put a cap on this???
+//Maybe...
+//                             if (pts.GetNumPoints() < 16)
+//                             {
+                               pt.x = lParam & 0xFFFF, pt.y = lParam >> 16;
+                               hdc = GetDC(hWnd);
+                               DPtoLP(hdc, &pt, 1);
+                               pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true));
+                               ptHighlight = ptNextHighlight;
+                               ReleaseDC(hWnd, hdc);
+                               InvalidateRect(hWnd, NULL, TRUE);
+//                             }
+                       }
+               }
+               else if (currentTool == TOOLAddPoly)    // "Add Poly" tool
+               {
+#ifdef DEBUGFOO
+wsprintf(strBuf, "Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints());
+WriteLogMsg(strBuf);
+#endif
+                       if (polyFirstPoint)
+                       {
+                               polyFirstPoint = false;
+                               pts.AddNewPolyAtEnd();
+                       }
+
+//Do we really need to put a cap on this???
+//Maybe...
+//                     if (pts.GetNumPoints() < 16)
+//                     {
+                       pt.x = lParam & 0xFFFF, pt.y = lParam >> 16;
+                       hdc = GetDC(hWnd);
+                       DPtoLP(hdc, &pt, 1);
+                       ReleaseDC(hWnd, hdc);
+                       // Append a point to the end of the structure
+                       pts += IPoint(pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true));
+ptHighlight = pts.GetNumPoints() - 1;
+                       InvalidateRect(hWnd, NULL, TRUE);
+//                     }
+#ifdef DEBUGFOO
+wsprintf(strBuf, " --> [# polys: %u, # points: %u]\xD\xA", pts.GetNumPolys(), pts.GetNumPoints());
+WriteLogMsg(strBuf);
+#endif
+               }
+               else if (currentTool == TOOLSelect || currentTool == TOOLPolySelect)
+               {
+                       if (pts.GetNumPoints() > 0)
+                       {
+                               pt.x = pts.GetX(ptHighlight), pt.y = pts.GetY(ptHighlight);
+                               hdc = GetDC(hWnd);
+                               LPtoDP(hdc, &pt, 1);
+                               ClientToScreen(hWnd, &pt);
+                               SetCursorPos(pt.x, pt.y);
+                               ReleaseDC(hWnd, hdc);
+
+                               if (wParam & (MK_SHIFT | MK_CONTROL))
+                                       pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight));
+                       }
+               }
+               else if (currentTool == TOOLDelPt)
+               {
+                       if (pts.GetNumPoints() > 0)
+//Or could use:
+//                     if (ptHighlight != -1)
+                       {
+//This assumes that WM_MOUSEMOVE happens before this!
+//The above commented out line should take care of this contingency... !!! FIX !!!
+                               pts.DeletePoint(ptHighlight);
+                               InvalidateRect(hWnd, NULL, TRUE);
+                       }
+               }
+
+               break;
+
+       case WM_LBUTTONUP:
+
+               mouseDown = false;
+
+               if (currentTool == TOOLScroll || currentTool == TOOLZoom)
+                       ReleaseCapture();
+
+               break;
+
+       case WM_MOUSEMOVE:
+
+               SetCursor(hCur[currentTool]);
+
+           // Extract current point from lParam/calc offset from previous point
+
+               pt.x = lParam & 0xFFFF, pt.y = lParam >> 16;
+               ptOffset.x = pt.x - ptPrevious.x,
+               ptOffset.y = pt.y - ptPrevious.y;
+
+               if (mouseDown)
+               {
+                       if (currentTool == TOOLScroll)
+                       {
+                               // NOTE: OffsetViewportOrg operates in DEVICE UNITS...
+
+                               hdc = GetDC(hWnd);
+                               OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL);
+                               ReleaseDC(hWnd, hdc);
+
+// this shows that it works, so the logic above must be faulty...
+// And it is. It should convert the coords first, then do the subtraction to figure the offset...
+// Above: DONE
+// Then multiply it by the scaling factor. Whee!
+
+                               InvalidateRect(hWnd, NULL, TRUE);
+//                             SendMessage(hWnd, WM_PAINT, NULL, NULL);
+                       }
+                       else if (currentTool == TOOLAddPt || currentTool == TOOLAddPoly || currentTool == TOOLSelect)
+                       {
+                               if (currentTool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch.
+                               {
+                                       POINT pt2;
+                                       pt2.x = pt.x, pt2.y = pt.y;
+                                       // Should also set onCurve here as well, depending on keystate
+//Or should we?
+                                       hdc = GetDC(hWnd);
+                                       DPtoLP(hdc, &pt2, 1);
+                                       pts.SetXY(ptHighlight, pt2.x, pt2.y);
+                                       ReleaseDC(hWnd, hdc);
+                                       InvalidateRect(hWnd, NULL, TRUE);
+                               }
+                       }
+                       else if (currentTool == TOOLPolySelect)
+                       {
+                               if (pts.GetNumPoints() > 0)
+                               {
+                                       POINT pt2;
+                                       pt2.x = pt.x, pt2.y = pt.y;
+                                       // Should also set onCurve here as well, depending on keystate
+//Or should we?
+                                       hdc = GetDC(hWnd);
+                                       DPtoLP(hdc, &pt2, 1);
+                                       pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight));
+                                       ReleaseDC(hWnd, hdc);
+                                       InvalidateRect(hWnd, NULL, TRUE);
+                               }
+                       }
+               }
+               else
+               {
+                       if (currentTool == TOOLSelect || currentTool == TOOLDelPt || currentTool == TOOLAddPt
+                               || currentTool == TOOLPolySelect)// || currentTool == TOOLAddPoly)
+                       {
+                               POINT pt2;
+                               pt2.x = pt.x, pt2.y = pt.y;
+                               hdc = GetDC(hWnd);
+                               DPtoLP(hdc, &pt2, 1);
+                               ReleaseDC(hWnd, hdc);
+
+                               double closest = 1.0e+99;
+
+                               for(int i=0; i<pts.GetNumPoints(); i++)
+                               {
+                                       double dist = ((pt2.x - pts.GetX(i)) * (pt2.x - pts.GetX(i)))
+                                               + ((pt2.y - pts.GetY(i)) * (pt2.y - pts.GetY(i)));
+
+                                       if (dist < closest)
+                                               closest = dist, ptHighlight = i;
+                               }
+
+                               if (ptHighlight != oldPtHighlight)
+                               {
+                                       oldPtHighlight = ptHighlight;
+                                       InvalidateRect(hWnd, NULL, TRUE);
+                               }
+
+                               // What follows here looks like voodoo, but is really simple. What we do is
+                               // check to see if the mouse point has a perpendicular intersection with any of
+                               // the line segments. If it does, calculate the length of the perpendicular
+                               // and choose the smallest length. If there is no perpendicular, then choose the
+                               // length of line connecting the closer of either the first endpoint or the
+                               // second and choose the smallest of those.
+
+                               // There is one bit of math that looks like voodoo to me ATM--will explain once
+                               // I understand it better (the calculation of the length of the perpendicular).
+
+                               if (pts.GetNumPoints() > 1 && currentTool == TOOLAddPt)
+                               {
+                                       double smallest = 1.0e+99;
+
+                                       for(int i=0; i<pts.GetNumPoints(); i++)
+                                       {
+                                               int32 p1x = pts.GetX(i), p1y = pts.GetY(i),
+                                                       p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i));
+
+                                               vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x, pt2.y, 0, p1x, p1y, 0),
+                                                       v2(pt2.x, pt2.y, 0, p2x, p2y, 0);
+                                               double pp = ls.dot(v1) / ls.length(), dist;
+// Geometric interpretation:
+// pp is the paremeterized point on the vector ls where the perpendicular intersects ls.
+// If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls,
+// then the perpendicular lies beyond the 2nd endpoint.
+
+                                               if (pp < 0.0)
+                                                       dist = v1.length();
+                                               else if (pp > ls.length())
+                                                       dist = v2.length();
+                                               else                                    // distance = ?Det?(ls, v1) / |ls|
+                                                       dist = abs((ls.x * v1.y - v1.x * ls.y) / ls.length());
+
+//The answer to the above looks like it might be found here:
+//
+//If the segment endpoints are s and e, and the point is p, then the test for the perpendicular
+//intercepting the segment is equivalent to insisting that the two dot products {s-e}.{s-p} and
+//{e-s}.{e-p} are both non-negative.  Perpendicular distance from the point to the segment is
+//computed by first computing the area of the triangle the three points form, then dividing by the
+//length of the segment.  Distances are done just by the Pythagorean theorem.  Twice the area of the
+//triangle formed by three points is the determinant of the following matrix:
+//
+//sx sy 1
+//ex ey 1
+//px py 1
+//
+//(???) By translating the start point to the origin, this can be rewritten as:
+//By subtracting row 1 from all rows, you get the following:
+//
+//0         0         0
+//(ex - sx) (ey - sy) 0
+//(px - sx) (py - sy) 0
+//
+//which greatly simplifies the calculation of the determinant.
+
+                                               if (dist < smallest)
+                                                       smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i;
+                                       }
+
+                                       if (ptNextHighlight != oldPtNextHighlight)
+                                       {
+                                               oldPtNextHighlight = ptNextHighlight;
+                                               InvalidateRect(hWnd, NULL, TRUE);
+                                       }
+                               }
+                       }
+               }
+
+               ptPrevious.x = pt.x, ptPrevious.y = pt.y;
+
+               break;
+
+       case WM_NOTIFY:
+
+               if (((NMHDR *)lParam)->code == TTN_NEEDTEXT)
+               {
+                       LoadString(hInst, ((TOOLTIPTEXT *)lParam)->hdr.idFrom + 0x80, toolTipTxt, 16);
+                       ((TOOLTIPTEXT *)lParam)->lpszText = toolTipTxt;
+               }
+
+               break;
+
+       case WM_MENUSELECT:
+       {
+               statusBarTxt[0] = 0;                                    // Clear status bar text
+               uint16 flags = wParam >> 16;                    // Extract flags
+
+               if (!(flags & MFT_SEPARATOR))
+               {
+                       uint16 id = wParam & 0xFFFF;
+
+                       if (flags & MF_POPUP)
+                       {
+                               if (flags & MF_SYSMENU)
+                                       id = IDS_SYSMENU;
+                               else
+                                       id = IDM_FILEMENU + wParam;
+                       }
+
+                       LoadString(hInst, id, statusBarTxt, 64);
+               }
+
+               SendMessage(hStatusBar, SB_SETTEXT, 0 + SBT_NOBORDERS, (LPARAM)statusBarTxt);
+               break;
+       }
+       case WM_COMMAND:
+       {
+               uint16 cmd = wParam & 0xFFFF;
+
+               if (cmd == IDM_NEW)
+               {
+//                   call   CmdIDM_NEW
+               }
+               else if (cmd == IDM_OPEN)
+               {
+//                   call   SaveChanges
+//                   .IF (eax)
+//                     movmov ofn.hwndOwner, eax, hMainWnd
+//                     mov    ofn.Flags, OFN_PATHMUSTEXIST + OFN_FILEMUSTEXIST
+//                     invoke GetOpenFileName, ADDR ofn
+//                     .IF (eax)
+////////
+//jmp @F
+//szDMsg1a     BYTE    "Could not open the file (GetOpenFileName)...", 0
+//szDMsg1b     BYTE    "Open error!", 0
+//szDMsg1c     BYTE    "About to attempt to open file...", 0
+//@@:
+////invoke MessageBox, hWnd, ADDR szDMsg1a, ADDR szDMsg1b, MB_ICONERROR or MB_OK
+//invoke MessageBox, hMainWnd, ADDR szDMsg1c, ADDR szFile, MB_ICONERROR or MB_OK
+//                       invoke LoadTTF, ADDR szFile
+//
+//////
+//                       // <<< FILE OPEN CODE HERE >>>
+//                       or     fFileStatus, NAMEDbit
+//                       and    fFileStatus, NOT CHANGEDbit
+//                       call   NewWindowName
+//                       mov    eax, TRUE      // return TRUE
+//                       jmp    Return
+//                       //��������������������������������������
+//OpenError:             invoke GetLastError
+//                       // <<< FILE OPEN ERROR CODE HERE >>>
+//                     .ENDIF
+//                     zero   eax      // return FALSE
+//                   .ENDIF
+               }
+               else if (cmd == IDM_SAVEAS)
+               {
+//                   and    fFileStatus, NOT NAMEDbit
+//                   call   CmdIDM_SAVE
+               }
+               else if (cmd == IDM_SAVE)
+               {
+//                   call   CmdIDM_SAVE
+               }
+               else if (cmd == IDM_ABOUT)
+                       DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ABOUT), hMainWnd, AboutProc, NULL);
+               else if (cmd == IDM_EXIT)
+                       SendMessage(hWnd, WM_CLOSE, 0, 0);
+               else if (cmd == ID_TBCHARWIN)
+               {
+                       ShowWindow(hCharWnd, (IsWindowVisible(hCharWnd) ? SW_HIDE : SW_SHOWNOACTIVATE));
+
+#ifdef DEBUGFOO
+wpC.length = sizeof(WINDOWPLACEMENT);
+GetWindowPlacement(hCharWnd, &wpC);
+wsprintf(strBuf, "Char window showCmd = %08X...\n", wpC.showCmd);
+WriteLogMsg(strBuf);
+#endif
+               }
+               else
+                       return DefWindowProc(hWnd, msgID, wParam, lParam);
+
+               break;
+       }
+       default:
+               return DefWindowProc(hWnd, msgID, wParam, lParam);
+       }
+
+       return 0;
+}
+
+//
+// Initialize TTF data
+//
+void CreateNewDoc(void)
+{
+}
+
+//
+// Save changes to document before quitting
+//
+bool SaveChanges(void)
+{
+       return true;
+}
+
+
+
+//
+// ABOUT Dialog WndProc
+//
+BOOL CALLBACK AboutProc(HWND hDlg, UINT msgID, WPARAM wParam, LPARAM lParam)
+{
+       switch (msgID)
+       {
+       case WM_INITDIALOG:
+
+               MiscCenterWnd(hDlg, hMainWnd);
+               break;
+
+       case WM_COMMAND:
+
+               if (wParam == IDOK || wParam == IDCANCEL)
+                       EndDialog(hDlg, TRUE);
+
+               break;
+
+       default:
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+//
+// Character Window WndProc
+//
+WndProcCW      PROC  STDCALL, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
+
+               mov    eax, uMsg                // pickup our message
+               .IF (eax == WM_PAINT)
+                 mov    eax, 0                 // Non-sense... (placeholder!)
+// Scan conversion etc. goes here...
+               .ELSEIF (eax == WM_LBUTTONDOWN)
+                 invoke SetCapture, hCharWnd
+               .ELSEIF (eax == WM_LBUTTONUP)
+                 invoke ReleaseCapture
+                 invoke SetFocus, hMainWnd     // Make sure the main wnd keeps focus!
+               .ELSEIF (eax == WM_NCLBUTTONDOWN)
+                 invoke DefWindowProc, hWnd, uMsg, wParam, lParam // Let it do its thing
+                 invoke SetFocus, hMainWnd     // Make sure the main wnd keeps focus!
+               .ELSE
+DefProc:         invoke DefWindowProc, hWnd, uMsg, wParam, lParam
+               .ENDIF
+               ret
+
+WndProcCW      ENDP
+
+//
+// Character Window WndProc
+//
+LRESULT CALLBACK WndProcCW(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
+{
+       switch (msgID)
+       {
+       default:
+               return DefWindowProc(hWnd, msgID, wParam, lParam);
+       }
+
+       return 0;
+}
+
+
+// Function prototypes
+
+int32 FindSelectedTool(void);
+
+//
+// Tool Palette WndProc
+//
+LRESULT CALLBACK WndProcTP(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
+{
+       PAINTSTRUCT ps;
+       HDC hdc;
+       POINT pt;
+       static uint32 prevTool = -1;
+
+       switch (msgID)
+       {
+       case WM_PAINT:
+       {
+               hdc = BeginPaint(hWnd, &ps);
+               HDC newDC = CreateCompatibleDC(NULL);
+               SelectObject(newDC, hBMToolPal1);
+               BitBlt(hdc, 0, 0, sizeTPBM.x, sizeTPBM.y, newDC, 0, 0, SRCCOPY);
+               DeleteDC(newDC);
+
+// This is crappy. Find some way to tighten this up!
+               int32 tool = FindSelectedTool();
+
+               if (tool != -1)
+               {
+                       newDC = CreateCompatibleDC(NULL);
+                       SelectObject(newDC, hBMToolPal1);
+                   //need ul corner of bitmap, ul corner of dest, width/height
+                       pt.x = sizeStamp.x * (tool & 0x03), pt.y = sizeStamp.y * (tool >> 2);
+                       BitBlt(hdc, pt.x, pt.y, sizeStamp.x, sizeStamp.y, newDC, pt.x, pt.y, NOTSRCCOPY);
+                       DeleteDC(newDC);
+               }
+
+               EndPaint(hWnd, &ps);
+               break;
+       }
+       case WM_MOUSEMOVE:
+       {
+               int32 tool = FindSelectedTool();
+
+               if (tool != prevTool)
+               {
+                       prevTool = tool;
+                       InvalidateRect(hWnd, NULL, FALSE);
+               }
+
+               break;
+       }
+       case WM_RBUTTONUP:
+       {
+               int32 tool = FindSelectedTool(), oldTool = currentTool;
+
+               if (tool != -1)
+                       currentTool = tool;
+
+               if (currentTool != TOOLSelect && currentTool != TOOLDelPt && currentTool != TOOLAddPt
+                       && currentTool != TOOLPolySelect)
+                       ptHighlight = -1;
+
+               if (currentTool != oldTool)
+                       InvalidateRect(hMainWnd, NULL, TRUE);
+
+               if (currentTool == TOOLAddPoly)
+#ifdef DEBUGFOO
+{
+#endif
+                       polyFirstPoint = true;
+#ifdef DEBUGFOO
+wsprintf(strBuf, "--> Selected poly tool, polyFirstPoint is %s\n", polyFirstPoint ? "true" : "false");
+WriteLogMsg(strBuf);
+}
+#endif
+
+               ReleaseCapture();
+               ShowWindow(hToolPalWnd, SW_HIDE);
+               SetFocus(hMainWnd);                                             // Make sure the main wnd keeps focus!
+
+               break;
+       }
+       default:
+               return DefWindowProc(hWnd, msgID, wParam, lParam);
+       }
+
+       return 0;
+}
+
+//
+// Find which tool we're pointing at
+// Use: xcoord = mouse.x / (bmsize.x/4), ycoord = mouse.y / (bmsize.y/2)
+//
+int32 FindSelectedTool(void)
+{
+       POINT pt;
+               
+       GetCursorPos(&pt);
+       ScreenToClient(hToolPalWnd, &pt);
+
+       uint32 x = (uint32)pt.x / sizeStamp.x, y = (uint32)pt.y / sizeStamp.y, tool = -1;
+
+       if (x < 4 && y < 2)
+//     {
+               tool = (y * 4) + x;
+
+//             if (tool == 7)
+//                     tool = -1;                                                      // 7 has no tool...
+//     }
+
+       return tool;
+}
+
+
+//
+// Misc center window
+//
+void MiscCenterWnd(HWND hChild, HWND hParent)
+{
+       RECT parent, child;
+
+       if (!GetWindowRect(hParent, &parent) || !GetWindowRect(hChild, &child))
+               return;
+
+       int32 x = parent.left + (((parent.right - parent.left) - (child.right - child.left)) / 2),
+               y = parent.top + (((parent.bottom - parent.top) - (child.bottom - child.top)) / 2);
+
+       if (x < 0)
+               x = 0;
+       else if (x > GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left))
+               x = GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left);
+
+       if (y < 0)
+               y = 0;
+       else if (y > GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top))
+               y = GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top);
+
+       SetWindowPos(hChild, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+}
+
+//
+// Allow only one instance
+//
+bool OnlyOneInstance(void)
+{
+       HWND window = FindWindow(className, NULL);
+
+       if (window == NULL)
+               return true;
+
+       ShowWindow(window, SW_SHOWNORMAL);
+       SetWindowPos(window, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+
+       return false;
+}
+
+//
+// Load/Allocate all resources
+//
+bool LoadResources(void)
+{
+       hCur[0] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR1));
+       hCur[1] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR2));
+       hCur[2] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR3));
+       hCur[3] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR4));
+       hCur[4] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR5));
+       hCur[5] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR6));
+       hCur[6] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR7));
+       hCur[7] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR8));
+
+       BITMAP bm;
+
+       hBMToolPal1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_TOOLPAL1));
+       GetObject(hBMToolPal1, sizeof(bm), &bm);
+
+       // Set up sizes
+
+       sizeTPBM.x = bm.bmWidth, sizeTPBM.y = bm.bmHeight;
+       sizeStamp.x = bm.bmWidth / 4, sizeStamp.y = bm.bmHeight / 2;
+
+       hBluePen1 = CreatePen(PS_DOT, 1, 0x00FF0000);
+       hRedPen1 = CreatePen(PS_SOLID, 1, 0x000000FF);
+       hGreenPen1 = CreatePen(PS_SOLID, 1, 0x0000AF00);
+       hBlackPen1 = CreatePen(PS_SOLID, 1, 0x00000000);
+
+       LOGBRUSH lb = { BS_NULL, 0, 0 };
+
+       hNullBrush = CreateBrushIndirect(&lb);
+
+       return true;
+}
+
+//
+// Deallocate all resources
+//
+void DeallocateResources(void)
+{
+       DeleteObject(hBMToolPal1);
+       DeleteObject(hBluePen1);
+       DeleteObject(hRedPen1);
+       DeleteObject(hGreenPen1);
+       DeleteObject(hBlackPen1);
+       DeleteObject(hNullBrush);
+}
+
+//
+// Save all application specific data, so we can pick up where we last left off...
+//
+void SaveAppState(void)
+{
+       SetINIInt("Main", "flags", wpM.flags);
+       SetINIInt("Main", "showCmd", wpM.showCmd);
+       SetINIInt("Main", "x1", wpM.rcNormalPosition.left);
+       SetINIInt("Main", "y1", wpM.rcNormalPosition.top);
+       SetINIInt("Main", "x2", wpM.rcNormalPosition.right);
+       SetINIInt("Main", "y2", wpM.rcNormalPosition.bottom);
+
+       SetINIInt("Main", "vpx", ptVPM.x);
+       SetINIInt("Main", "vpy", ptVPM.y);
+
+       SetINIInt("Char", "flags", wpC.flags);
+       SetINIInt("Char", "showCmd", wpC.showCmd);
+       SetINIInt("Char", "x1", wpC.rcNormalPosition.left);
+       SetINIInt("Char", "y1", wpC.rcNormalPosition.top);
+       SetINIInt("Char", "x2", wpC.rcNormalPosition.right);
+       SetINIInt("Char", "y2", wpC.rcNormalPosition.bottom);
+
+       // Need to write out currently opened font, character looking at, other misc. crap
+//     SetINIString("Main", "currentFile", pDoc->GetPathName());
+//     SetINIInt("Main", "currentChar", pDoc->character_num);
+}
+
+//
+// Restore all application specific data previously saved
+//
+bool RestoreAppState(void)
+{
+       InitINIFile();
+
+       WINDOWPLACEMENT wp;
+       wp.length = sizeof(WINDOWPLACEMENT);
+       GetWindowPlacement(hMainWnd, &wp);
+
+       wp.flags = GetINIInt("Main", "flags", wp.flags);
+       wp.showCmd = GetINIInt("Main", "showCmd", wp.showCmd);
+       wp.rcNormalPosition.left = GetINIInt("Main", "x1", wp.rcNormalPosition.left);
+       wp.rcNormalPosition.top = GetINIInt("Main", "y1", wp.rcNormalPosition.top);
+       wp.rcNormalPosition.right = GetINIInt("Main", "x2", wp.rcNormalPosition.right);
+       wp.rcNormalPosition.bottom = GetINIInt("Main", "y2", wp.rcNormalPosition.bottom);
+
+       SetWindowPlacement(hMainWnd, &wp);
+
+       HDC hdc;
+       POINT pt;
+       hdc = GetDC(hMainWnd);
+       GetViewportOrgEx(hdc, &pt);
+
+       pt.x = GetINIInt("Main", "vpx", pt.x);
+       pt.y = GetINIInt("Main", "vpy", pt.y);
+
+       SetViewportOrgEx(hdc, pt.x, pt.y, NULL);
+       ReleaseDC(hMainWnd, hdc);
+
+       GetWindowPlacement(hCharWnd, &wp);
+
+       wp.flags = GetINIInt("Char", "flags", wp.flags);
+       wp.showCmd = GetINIInt("Char", "showCmd", wp.showCmd);
+       wp.rcNormalPosition.left = GetINIInt("Char", "x1", wp.rcNormalPosition.left);
+       wp.rcNormalPosition.top = GetINIInt("Char", "y1", wp.rcNormalPosition.top);
+       wp.rcNormalPosition.right = GetINIInt("Char", "x2", wp.rcNormalPosition.right);
+       wp.rcNormalPosition.bottom = GetINIInt("Char", "y2", wp.rcNormalPosition.bottom);
+
+       SetWindowPlacement(hCharWnd, &wp);
+
+       if (wp.showCmd == SW_HIDE)
+               SendMessage(hToolBar, TB_SETSTATE, ID_TBCHARWIN, MAKELONG(TBSTATE_ENABLED, 0));
+
+//  CString lastFile = theApplicationObject.GetProfileString(version, "currentFile", "");
+//  int lastChar = theApplicationObject.GetProfileInt(version, "currentChar", 0);
+//  if (lastFile.GetLength())
+//  {
+//    // Attempt to restore the last session by open the last file used, etc...
+//    if (!pDoc->m_myFont.Load(lastFile))
+//    {
+//      // Err, make sure you can support any allegations you make below, buddy!
+//      AfxMessageBox("The last file opened with TTF Edit\n\rseems to have been moved or deleted.");
+//    }
+//    else
+//    {
+//      pDoc->m_myFont.SetGlyph(lastChar);  // Set TTF object to last used char
+//      pDoc->character_num = lastChar;
+//      pDoc->SetPathName(lastFile);
+//
+//      BYTE name[512];
+//      pDoc->m_myFont.GetCharName(lastChar, name);
+//      m_wndOwned.SetWindowText((char *)name);
+//    }
+//  }
+
+       return true;
+}
+
+//
+// Initialization
+//
+bool Initialization(void)
+{
+       WNDCLASSEX wcex;
+
+       if (!LoadResources())
+               return false;
+
+       RtlFillMemory(&wcex, sizeof(WNDCLASSEX), 0);
+       wcex.cbSize = sizeof(WNDCLASSEX);
+       wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+       wcex.lpfnWndProc = WndProc;
+       wcex.hInstance = hInst;
+       wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON));
+       wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+       wcex.lpszMenuName = MAKEINTRESOURCE(IDM_MENU);
+       wcex.lpszClassName = className;
+       wcex.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, NULL);
+
+       if (!RegisterClassEx(&wcex))
+               return false;
+
+       hMainWnd = CreateWindowEx(NULL, className, className, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
+               0, 0, 0x1A0, 0x180, NULL, NULL, hInst, NULL);
+
+       if (!hMainWnd)
+               return false;
+
+       ShowWindow(hMainWnd, nCmdShow);
+       UpdateWindow(hMainWnd);
+
+       // Character window creation
+
+       wcex.lpfnWndProc = WndProcCW;
+       wcex.lpszMenuName = NULL;
+       wcex.lpszClassName = CNCharWin;
+       wcex.hCursor = LoadCursor(NULL, IDC_ARROW);     // Owned windows have "regular" cursors
+
+       if (!RegisterClassEx(&wcex))
+               return false;
+
+       hCharWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW, CNCharWin,
+               curCharName, WS_POPUP | WS_CAPTION | WS_VISIBLE | WS_THICKFRAME,
+               100, 100, 120, 120, hMainWnd, NULL, hInst, NULL);
+
+       if (!hCharWnd)
+               return false;
+
+       ShowWindow(hCharWnd, SW_SHOWNORMAL);
+       UpdateWindow(hCharWnd);
+       SetFocus(hMainWnd);                                                     // Make sure main wnd has focus!
+
+       // Tool palette window creation
+
+       wcex.lpfnWndProc = WndProcTP;
+       wcex.lpszClassName = CNToolPal;
+
+       if (!RegisterClassEx(&wcex))
+               return false;
+
+       hToolPalWnd = CreateWindowEx(WS_EX_WINDOWEDGE, CNToolPal, NULL, WS_POPUP,
+               0, 0, sizeTPBM.x, sizeTPBM.y, hMainWnd, NULL, hInst, NULL);
+
+       if (!hToolPalWnd)
+               return false;
+
+// Note: A better way to handle this would be to have a sub that registers ALL
+//       classes beforehand and passes a TRUE/FALSE back depending on whether or not
+//       all the classes were able to be registered or not, THEN create the windows
+//       and controls...
+
+       RestoreAppState();                                                      // Restore app related stuff
+
+       return true;
+}
+
+#endif
index 4d0a9319725a316d11a0a294d04004b1630fe889..846e891608342f6084855e7b8d5c83bb9f94dd60 100755 (executable)
@@ -1,48 +1,48 @@
-//\r
-// EDITWINDOW.H: Header file\r
-//\r
-// by James L. Hammons\r
-// (C) 2008 Underground Software\r
-//\r
-\r
-#ifndef __EDITWINDOW_H__\r
-#define __EDITWINDOW_H__\r
-\r
-#include <wx/wx.h>                                                             // So that whoever uses this can without having\r
-                                                                                               // to pull in a bunch of references manually\r
-#include "types.h"\r
-#include "ttedit.h"                                                            // For TTEditApp\r
-#include "toolwindow.h"                                                        // For ToolType enum\r
-#include "glyphpoints.h"\r
-\r
-class TTEditWindow: public wxWindow\r
-{\r
-       private:\r
-               TTEditApp & app;                                                // Reference to the application object\r
-               double scale;                                                   // Window scaling factor\r
-               int32 offsetX, offsetY;                                 // Window offsets\r
-               ToolType tool;                                                  // Current tool\r
-               GlyphPoints pts;                                                // Glyph point structure\r
-               int32 ptHighlight, oldPtHighlight, ptNextHighlight, oldPtNextHighlight;\r
-               bool polyFirstPoint;\r
-\r
-       protected:\r
-       public:\r
-               wxBitmap * bmp;\r
-               wxPoint pt, ptOffset, ptPrevious;\r
-\r
-               // Constructor and destructor\r
-               TTEditWindow(wxFrame * parent, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0);\r
-               ~TTEditWindow(void);\r
-\r
-               void OnPaint(wxPaintEvent &e);\r
-               void OnMouseEvent(wxMouseEvent &e);\r
-\r
-       protected:\r
-               wxPoint GetAdjustedMousePosition(wxMouseEvent &e);\r
-               wxPoint GetAdjustedClientPosition(wxCoord x, wxCoord y);\r
-\r
-       DECLARE_EVENT_TABLE()\r
-};\r
-\r
-#endif // __EDITWINDOW_H__\r
+//
+// EDITWINDOW.H: Header file
+//
+// by James L. Hammons
+// (C) 2008 Underground Software
+//
+
+#ifndef __EDITWINDOW_H__
+#define __EDITWINDOW_H__
+
+#include <wx/wx.h>                                                             // So that whoever uses this can without having
+                                                                                               // to pull in a bunch of references manually
+#include "types.h"
+#include "ttedit.h"                                                            // For TTEditApp
+#include "toolwindow.h"                                                        // For ToolType enum
+#include "glyphpoints.h"
+
+class TTEditWindow: public wxWindow
+{
+       private:
+               TTEditApp & app;                                                // Reference to the application object
+               double scale;                                                   // Window scaling factor
+               int32 offsetX, offsetY;                                 // Window offsets
+               ToolType tool;                                                  // Current tool
+               GlyphPoints pts;                                                // Glyph point structure
+               int32 ptHighlight, oldPtHighlight, ptNextHighlight, oldPtNextHighlight;
+               bool polyFirstPoint;
+
+       protected:
+       public:
+               wxBitmap * bmp;
+               wxPoint pt, ptOffset, ptPrevious;
+
+               // Constructor and destructor
+               TTEditWindow(wxFrame * parent, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0);
+               ~TTEditWindow(void);
+
+               void OnPaint(wxPaintEvent &e);
+               void OnMouseEvent(wxMouseEvent &e);
+
+       protected:
+               wxPoint GetAdjustedMousePosition(wxMouseEvent &e);
+               wxPoint GetAdjustedClientPosition(wxCoord x, wxCoord y);
+
+       DECLARE_EVENT_TABLE()
+};
+
+#endif // __EDITWINDOW_H__
index a2b80aa499fa4098cedcaa7f2add13d378ee7a00..d0402f6fe041ddc800a29b03db00a24c53d9439f 100755 (executable)
-//\r
-// GLYPHPOINTS.CPP\r
-//\r
-// Class implementation. Nothing too inexplicable going on here. Fairly\r
-// straightforward stuff.\r
-//\r
-// by James L. Hammons\r
-// (C) 2004 Underground Software\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  ------------------------------------------------------------\r
-// JLH  ??/??/200?  Created this file\r
-// JLH  05/18/2004  Added pure point adding, inserting, better polygon handling\r
-//\r
-\r
-// Uncomment this for debugging...\r
-#define DEBUG\r
-\r
-#include "glyphpoints.h"\r
-#ifdef DEBUG\r
-#include "debug.h"\r
-#endif\r
-\r
-/*GlyphPoints::GlyphPoints(void)\r
-{\r
-       GlyphPoints(0, 0, NULL, NULL, NULL, NULL);\r
-}*/\r
-\r
-GlyphPoints::GlyphPoints(int nPts/*=0*/, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,\r
-       bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)\r
-//GlyphPoints::GlyphPoints(int nPts, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,\r
-//     bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)\r
-{\r
-       AllocateAndCopy(nPts, nPlys, xa, ya, oca, pa);\r
-\r
-       if (nPlys == 0)\r
-       {\r
-               numPolys = 1;\r
-               polyEnd = new uint16[numPolys];\r
-               polyEnd[0] = numPoints - 1;\r
-       }\r
-#ifdef DEBUG\r
-WriteLogMsg("GlyphPoints: Default constructor. %u points, %u polys.\n", numPoints, numPolys);\r
-#endif\r
-}\r
-\r
-GlyphPoints::GlyphPoints(int xx, int yy, bool oc)\r
-{\r
-//Hmm. What to do with this...?\r
-       AllocateAndCopy(1, 0, &xx, &yy, &oc, NULL);\r
-#ifdef DEBUG\r
-WriteLogMsg("GlyphPoints: Single point constructor. %u points, %u polys.\n", numPoints, numPolys);\r
-#endif\r
-}\r
-\r
-// Copy constructor (needed for deep copying)\r
-\r
-//GlyphPoints::GlyphPoints(GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)\r
-GlyphPoints::GlyphPoints(const GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)\r
-{\r
-       *this = c;                                                                      // Use overloaded operator=\r
-#ifdef DEBUG\r
-WriteLogMsg("GlyphPoints: Copy constructor. %u points, %u polys.\n", numPoints, numPolys);\r
-#endif\r
-}\r
-\r
-GlyphPoints::~GlyphPoints()\r
-{\r
-       if (x)\r
-               delete[] x;\r
-\r
-       if (y)\r
-               delete[] y;\r
-\r
-       if (onCurve)\r
-               delete[] onCurve;\r
-\r
-       if (polyEnd)\r
-               delete[] polyEnd;\r
-}\r
-\r
-void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool * oca, uint16 * pa)\r
-{\r
-       numPoints = nPts, numPolys = nPlys;\r
-\r
-       if (nPts)\r
-       {\r
-               x = new int[numPoints];\r
-               y = new int[numPoints];\r
-               onCurve = new bool[numPoints];\r
-\r
-               if (xa)                                                                 // Copy points in if they're passed in...\r
-                       for(int i=0; i<nPts; i++)\r
-                               x[i] = xa[i];\r
-\r
-               if (ya)\r
-                       for(int i=0; i<nPts; i++)\r
-                               y[i] = ya[i];\r
-\r
-               if (oca)\r
-                       for(int i=0; i<nPts; i++)\r
-                               onCurve[i] = oca[i];\r
-       }\r
-\r
-       if (numPolys)\r
-       {\r
-               polyEnd = new uint16[numPolys];\r
-\r
-               if (pa)                                                                 // Copy poly ends in if they're passed in...\r
-                       for(int i=0; i<nPlys; i++)\r
-                               polyEnd[i] = pa[i];\r
-       }\r
-}\r
-\r
-GlyphPoints& GlyphPoints::operator=(const GlyphPoints &c)\r
-{\r
-       if (this == &c)\r
-               return *this;                                                   // Take care of self-assignment\r
-\r
-       if (x)\r
-               delete[] x;\r
-\r
-       if (y)\r
-               delete[] y;\r
-\r
-       if (onCurve)\r
-               delete[] onCurve;\r
-\r
-       if (polyEnd)\r
-               delete[] polyEnd;\r
-\r
-       AllocateAndCopy(c.numPoints, c.numPolys, c.x, c.y, c.onCurve, c.polyEnd);\r
-\r
-       return *this;\r
-}\r
-\r
-// Add another GlyphPoints' points to this one...\r
-\r
-GlyphPoints GlyphPoints::operator+(const GlyphPoints &c)\r
-{\r
-       int totPoints = numPoints + c.numPoints, totPolys = numPolys + c.numPolys;\r
-\r
-       int * totX = new int[totPoints];\r
-       int * totY = new int[totPoints];\r
-       bool * totOnCurve = new bool[totPoints];\r
-       uint16 * totPolyEnd = new uint16[totPolys];\r
-\r
-       for(int i=0; i<numPoints; i++)\r
-       {\r
-               totX[i] = x[i];\r
-               totY[i] = y[i];\r
-               totOnCurve[i] = onCurve[i];\r
-       }\r
-\r
-       for(int i=0; i<numPolys; i++)\r
-               totPolyEnd[i] = polyEnd[i];\r
-\r
-       for(int i=0; i<c.numPoints; i++)\r
-       {\r
-               totX[numPoints+i] = c.x[i];\r
-               totY[numPoints+i] = c.y[i];\r
-               totOnCurve[numPoints+i] = c.onCurve[i];\r
-       }\r
-\r
-       for(int i=0; i<c.numPolys; i++)\r
-               totPolyEnd[numPolys+i] = numPoints + c.polyEnd[i];  // Need to adjust the "added in"\r
-                                                        // poly's end points...\r
-\r
-       GlyphPoints retVal(totPoints, totPolys, totX, totY, totOnCurve, totPolyEnd);\r
-       delete[] totX;\r
-       delete[] totY;\r
-       delete[] totOnCurve;\r
-       delete[] totPolyEnd;\r
-\r
-       return retVal;\r
-}\r
-\r
-// Add a point to this GlyphPoints...\r
-\r
-GlyphPoints GlyphPoints::operator+(const IPoint &c)\r
-{\r
-//This is kinda silly. We can do better than this! !!! FIX !!!\r
-       int * totX = new int[numPoints + 1];\r
-       int * totY = new int[numPoints + 1];\r
-       bool * totOnCurve = new bool[numPoints + 1];\r
-       uint16 * totPolyEnd = new uint16[numPolys];\r
-\r
-       for(int i=0; i<numPoints; i++)\r
-               totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];\r
-\r
-       totX[numPoints] = c.x, totY[numPoints] = c.y, totOnCurve[numPoints] = c.onCurve;\r
-\r
-       for(int i=0; i<numPolys; i++)\r
-               totPolyEnd[i] = polyEnd[i];\r
-\r
-       totPolyEnd[numPolys - 1]++;                                     // Bump polygon's end point\r
-       GlyphPoints retVal(numPoints + 1, numPolys, totX, totY, totOnCurve, totPolyEnd);\r
-\r
-       delete[] totX;\r
-       delete[] totY;\r
-       delete[] totOnCurve;\r
-\r
-       return retVal;\r
-}\r
-\r
-GlyphPoints& GlyphPoints::operator+=(const IPoint &p)\r
-{\r
-       InsertPoint(numPoints, p.x, p.y, p.onCurve);\r
-\r
-       return *this;\r
-}\r
-\r
-void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc)\r
-{\r
-       if (pt > numPoints)                                                     // > because we can insert at end...!\r
-               throw GP_OUT_OF_RANGE;\r
-\r
-//This is kinda silly. We can do better than this! !!! FIX !!!\r
-       int * totX = new int[numPoints + 1];\r
-       int * totY = new int[numPoints + 1];\r
-       bool * totOnCurve = new bool[numPoints + 1];\r
-\r
-       for(int i=0; i<pt; i++)\r
-               totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];\r
-\r
-       for(int i=pt; i<numPoints; i++)\r
-               totX[i + 1] = x[i], totY[i + 1] = y[i], totOnCurve[i + 1] = onCurve[i];\r
-\r
-       totX[pt] = xx, totY[pt] = yy, totOnCurve[pt] = oc;\r
-\r
-//A way to fix the kludge in GetPoly() would be to put a check here to see if \r
-//we're adding to the end of the structure: [DONE, below]\r
-       int polyInsert = (pt == numPoints ? numPolys - 1 : GetPoly(pt));\r
-       for(int i=polyInsert; i<numPolys; i++)\r
-//     for(int i=GetPoly(pt); i<numPolys; i++)\r
-               polyEnd[i]++;                                                   // Bump polygons' end point\r
-\r
-       numPoints++;\r
-\r
-       delete[] x;\r
-       delete[] y;\r
-       delete[] onCurve;\r
-\r
-       x = totX, y = totY, onCurve = totOnCurve;\r
-}\r
-\r
-void GlyphPoints::InsertPoint(uint16 pt, const IPoint &p)\r
-{\r
-       InsertPoint(pt, p.x, p.y, p.onCurve);\r
-}\r
-\r
-//\r
-// Delete a point from the glyph\r
-// Note that we don't bother to reallocate anything here, just bump the\r
-// size counters down as needed. In the future, we'll keep track so we\r
-// don't have to reallocate *every* damn time a point is added...\r
-//\r
-void GlyphPoints::DeletePoint(uint16 pt)\r
-{\r
-       // Adjust polygon ends appropriately\r
-       uint16 poly = GetPoly(pt);\r
-\r
-       for(int i=poly; i<numPolys; i++)\r
-               polyEnd[i]--;\r
-\r
-//Need to check here if we're deleting the last point in the glyph or not.\r
-//!!! FIX !!! [DONE]\r
-       if (GetNumPoints(poly) == 0 && numPoints > 0)\r
-       {\r
-               numPolys--;\r
-\r
-               for(int i=poly; i<numPolys; i++)\r
-                       polyEnd[i] = polyEnd[i + 1];\r
-       }\r
-\r
-//This causes a crash becuz GetPoly() uses numPoints... !!! FIX !!! [DONE by switching poly delete & point delete]\r
-       // Close up the gap left by the current point\r
-       numPoints--;\r
-\r
-       for(int i=pt; i<numPoints; i++)\r
-               x[i] = x[i + 1], y[i] = y[i + 1], onCurve[i] = onCurve[i + 1];\r
-}\r
-\r
-uint16 GlyphPoints::GetNumPoints(void)\r
-{\r
-       return numPoints;\r
-}\r
-\r
-uint16 GlyphPoints::GetNumPoints(uint16 poly)\r
-{\r
-       if (poly >= numPolys)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetNumPoints(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       return polyEnd[poly] - (poly == 0 ? -1 : polyEnd[poly - 1]);\r
-}\r
-\r
-uint16 GlyphPoints::GetNumPolys(void)\r
-{\r
-       return numPolys;\r
-}\r
-\r
-int GlyphPoints::GetX(uint16 pt)\r
-{\r
-       if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetX(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       return x[pt];\r
-}\r
-\r
-int GlyphPoints::GetY(uint16 pt)\r
-{\r
-       if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetY(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       return y[pt];\r
-}\r
-\r
-bool GlyphPoints::GetOnCurve(uint16 pt)\r
-{\r
-       if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetOnCurve(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       return onCurve[pt];\r
-}\r
-\r
-int GlyphPoints::GetX(uint16 poly, uint16 pt)\r
-{\r
-       if (pt >= GetNumPoints(poly))\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetX(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       return x[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];\r
-}\r
-\r
-int GlyphPoints::GetY(uint16 poly, uint16 pt)\r
-{\r
-       if (pt >= GetNumPoints(poly))\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetY(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       return y[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];\r
-}\r
-\r
-bool GlyphPoints::GetOnCurve(uint16 poly, uint16 pt)\r
-{\r
-       if (pt >= GetNumPoints(poly))\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetOnCurve(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       return onCurve[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];\r
-}\r
-\r
-uint16 GlyphPoints::GetPolyEnd(uint16 poly)\r
-{\r
-       if (poly >= numPolys)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       return polyEnd[poly];\r
-}\r
-\r
-void GlyphPoints::OffsetPoints(int xOff, int yOff)\r
-{\r
-       for(int i=0; i<numPoints; i++)\r
-               x[i] += xOff, y[i] += yOff;\r
-}\r
-\r
-//\r
-// Offset only a specific polygon in the glyph\r
-//\r
-void GlyphPoints::OffsetPoly(uint16 poly, int32 xOff, int32 yOff)\r
-{\r
-       if (poly >= numPolys)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       uint16 polyStart = (poly == 0 ? 0 : polyEnd[poly - 1] + 1);\r
-\r
-       for(int i=0; i<GetNumPoints(poly); i++)\r
-               x[polyStart + i] += xOff, y[polyStart + i] += yOff;\r
-}\r
-\r
-void GlyphPoints::ScalePoints(float sc)\r
-{\r
-       for(int i=0; i<numPoints; i++)\r
-               x[i] = (int)(((float)x[i] * sc) + 0.5f),\r
-               y[i] = (int)(((float)y[i] * sc) + 0.5f);\r
-}\r
-\r
-void GlyphPoints::SetXY(uint16 pt, int xx, int yy)\r
-{\r
-       if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: SetXY(uint16, int, int). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       x[pt] = xx, y[pt] = yy;\r
-}\r
-\r
-void GlyphPoints::SetOnCurve(uint16 pt, bool oc)\r
-{\r
-       if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: SetOnCurve(uint16, bool). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       onCurve[pt] = oc;\r
-}\r
-\r
-uint16 GlyphPoints::GetPrev(uint16 pt)\r
-{\r
-// pt = 7, polyEnd = 4, 9, 15\r
-       uint16 min = 0, max = numPoints - 1;\r
-\r
-       for(int i=0; i<numPolys; i++)\r
-       {\r
-               if (pt <= polyEnd[i])\r
-               {\r
-                       if (i > 0)\r
-                               min = polyEnd[i - 1] + 1;\r
-\r
-                       max = polyEnd[i];\r
-                       break;\r
-               }\r
-       }\r
-\r
-       uint16 retVal = pt - 1;\r
-\r
-       if (pt == min)\r
-               retVal = max;\r
-\r
-       return retVal;\r
-}\r
-\r
-uint16 GlyphPoints::GetNext(uint16 pt)\r
-{\r
-       uint16 min = 0, max = numPoints - 1;\r
-\r
-       for(int i=0; i<numPolys; i++)\r
-       {\r
-               if (pt <= polyEnd[i])\r
-               {\r
-                       if (i > 0)\r
-                               min = polyEnd[i - 1] + 1;\r
-\r
-                       max = polyEnd[i];\r
-                       break;\r
-               }\r
-       }\r
-\r
-       uint16 retVal = pt + 1;\r
-\r
-       if (pt == max)\r
-               retVal = min;\r
-\r
-       return retVal;\r
-}\r
-\r
-//\r
-// Get previous point for this polygon using wraparound.\r
-// Note that pt is a zero-based index!\r
-//\r
-uint16 GlyphPoints::GetPrev(uint16 poly, uint16 pt)\r
-{\r
-       return (pt == 0 ? GetNumPoints(poly) - 1 : pt - 1);\r
-}\r
-\r
-//\r
-// Get next point for this polygon using wraparound.\r
-// Note that pt is a zero-based index!\r
-//\r
-uint16 GlyphPoints::GetNext(uint16 poly, uint16 pt)\r
-{\r
-       return (pt == GetNumPoints(poly) - 1 ? 0 : pt + 1);\r
-}\r
-\r
-uint16 GlyphPoints::GetPoly(uint16 pt)\r
-{\r
-       if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetPoly(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
-               throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
-       for(int i=0; i<numPolys; i++)\r
-               if (pt <= polyEnd[i])\r
-                       return i;\r
-\r
-       return (uint16)-1;\r
-}\r
-\r
-void GlyphPoints::AddNewPolyAtEnd(void)\r
-{\r
-       if (numPoints == 0)                                                     // By default, we already *have* a poly\r
-               return;\r
-\r
-       uint16 * newPolyEnd = new uint16[numPolys + 1];\r
-\r
-       for(uint16 i=0; i<numPolys; i++)\r
-               newPolyEnd[i] = polyEnd[i];\r
-\r
-       newPolyEnd[numPolys] = newPolyEnd[numPolys - 1];\r
-       numPolys++;\r
-       delete[] polyEnd;\r
-       polyEnd = newPolyEnd;\r
-}\r
-\r
+//
+// GLYPHPOINTS.CPP
+//
+// Class implementation. Nothing too inexplicable going on here. Fairly
+// straightforward stuff.
+//
+// by James L. Hammons
+// (C) 2004 Underground Software
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  ------------------------------------------------------------
+// JLH  ??/??/200?  Created this file
+// JLH  05/18/2004  Added pure point adding, inserting, better polygon handling
+//
+
+// Uncomment this for debugging...
+#define DEBUG
+
+#include "glyphpoints.h"
+#ifdef DEBUG
+#include "debug.h"
+#endif
+
+/*GlyphPoints::GlyphPoints(void)
+{
+       GlyphPoints(0, 0, NULL, NULL, NULL, NULL);
+}*/
+
+GlyphPoints::GlyphPoints(int nPts/*=0*/, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,
+       bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
+//GlyphPoints::GlyphPoints(int nPts, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,
+//     bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
+{
+       AllocateAndCopy(nPts, nPlys, xa, ya, oca, pa);
+
+       if (nPlys == 0)
+       {
+               numPolys = 1;
+               polyEnd = new uint16[numPolys];
+               polyEnd[0] = numPoints - 1;
+       }
+#ifdef DEBUG
+WriteLogMsg("GlyphPoints: Default constructor. %u points, %u polys.\n", numPoints, numPolys);
+#endif
+}
+
+GlyphPoints::GlyphPoints(int xx, int yy, bool oc)
+{
+//Hmm. What to do with this...?
+       AllocateAndCopy(1, 0, &xx, &yy, &oc, NULL);
+#ifdef DEBUG
+WriteLogMsg("GlyphPoints: Single point constructor. %u points, %u polys.\n", numPoints, numPolys);
+#endif
+}
+
+// Copy constructor (needed for deep copying)
+
+//GlyphPoints::GlyphPoints(GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
+GlyphPoints::GlyphPoints(const GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
+{
+       *this = c;                                                                      // Use overloaded operator=
+#ifdef DEBUG
+WriteLogMsg("GlyphPoints: Copy constructor. %u points, %u polys.\n", numPoints, numPolys);
+#endif
+}
+
+GlyphPoints::~GlyphPoints()
+{
+       if (x)
+               delete[] x;
+
+       if (y)
+               delete[] y;
+
+       if (onCurve)
+               delete[] onCurve;
+
+       if (polyEnd)
+               delete[] polyEnd;
+}
+
+void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool * oca, uint16 * pa)
+{
+       numPoints = nPts, numPolys = nPlys;
+
+       if (nPts)
+       {
+               x = new int[numPoints];
+               y = new int[numPoints];
+               onCurve = new bool[numPoints];
+
+               if (xa)                                                                 // Copy points in if they're passed in...
+                       for(int i=0; i<nPts; i++)
+                               x[i] = xa[i];
+
+               if (ya)
+                       for(int i=0; i<nPts; i++)
+                               y[i] = ya[i];
+
+               if (oca)
+                       for(int i=0; i<nPts; i++)
+                               onCurve[i] = oca[i];
+       }
+
+       if (numPolys)
+       {
+               polyEnd = new uint16[numPolys];
+
+               if (pa)                                                                 // Copy poly ends in if they're passed in...
+                       for(int i=0; i<nPlys; i++)
+                               polyEnd[i] = pa[i];
+       }
+}
+
+GlyphPoints& GlyphPoints::operator=(const GlyphPoints &c)
+{
+       if (this == &c)
+               return *this;                                                   // Take care of self-assignment
+
+       if (x)
+               delete[] x;
+
+       if (y)
+               delete[] y;
+
+       if (onCurve)
+               delete[] onCurve;
+
+       if (polyEnd)
+               delete[] polyEnd;
+
+       AllocateAndCopy(c.numPoints, c.numPolys, c.x, c.y, c.onCurve, c.polyEnd);
+
+       return *this;
+}
+
+// Add another GlyphPoints' points to this one...
+
+GlyphPoints GlyphPoints::operator+(const GlyphPoints &c)
+{
+       int totPoints = numPoints + c.numPoints, totPolys = numPolys + c.numPolys;
+
+       int * totX = new int[totPoints];
+       int * totY = new int[totPoints];
+       bool * totOnCurve = new bool[totPoints];
+       uint16 * totPolyEnd = new uint16[totPolys];
+
+       for(int i=0; i<numPoints; i++)
+       {
+               totX[i] = x[i];
+               totY[i] = y[i];
+               totOnCurve[i] = onCurve[i];
+       }
+
+       for(int i=0; i<numPolys; i++)
+               totPolyEnd[i] = polyEnd[i];
+
+       for(int i=0; i<c.numPoints; i++)
+       {
+               totX[numPoints+i] = c.x[i];
+               totY[numPoints+i] = c.y[i];
+               totOnCurve[numPoints+i] = c.onCurve[i];
+       }
+
+       for(int i=0; i<c.numPolys; i++)
+               totPolyEnd[numPolys+i] = numPoints + c.polyEnd[i];  // Need to adjust the "added in"
+                                                        // poly's end points...
+
+       GlyphPoints retVal(totPoints, totPolys, totX, totY, totOnCurve, totPolyEnd);
+       delete[] totX;
+       delete[] totY;
+       delete[] totOnCurve;
+       delete[] totPolyEnd;
+
+       return retVal;
+}
+
+// Add a point to this GlyphPoints...
+
+GlyphPoints GlyphPoints::operator+(const IPoint &c)
+{
+//This is kinda silly. We can do better than this! !!! FIX !!!
+       int * totX = new int[numPoints + 1];
+       int * totY = new int[numPoints + 1];
+       bool * totOnCurve = new bool[numPoints + 1];
+       uint16 * totPolyEnd = new uint16[numPolys];
+
+       for(int i=0; i<numPoints; i++)
+               totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];
+
+       totX[numPoints] = c.x, totY[numPoints] = c.y, totOnCurve[numPoints] = c.onCurve;
+
+       for(int i=0; i<numPolys; i++)
+               totPolyEnd[i] = polyEnd[i];
+
+       totPolyEnd[numPolys - 1]++;                                     // Bump polygon's end point
+       GlyphPoints retVal(numPoints + 1, numPolys, totX, totY, totOnCurve, totPolyEnd);
+
+       delete[] totX;
+       delete[] totY;
+       delete[] totOnCurve;
+
+       return retVal;
+}
+
+GlyphPoints& GlyphPoints::operator+=(const IPoint &p)
+{
+       InsertPoint(numPoints, p.x, p.y, p.onCurve);
+
+       return *this;
+}
+
+void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc)
+{
+       if (pt > numPoints)                                                     // > because we can insert at end...!
+               throw GP_OUT_OF_RANGE;
+
+//This is kinda silly. We can do better than this! !!! FIX !!!
+       int * totX = new int[numPoints + 1];
+       int * totY = new int[numPoints + 1];
+       bool * totOnCurve = new bool[numPoints + 1];
+
+       for(int i=0; i<pt; i++)
+               totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];
+
+       for(int i=pt; i<numPoints; i++)
+               totX[i + 1] = x[i], totY[i + 1] = y[i], totOnCurve[i + 1] = onCurve[i];
+
+       totX[pt] = xx, totY[pt] = yy, totOnCurve[pt] = oc;
+
+//A way to fix the kludge in GetPoly() would be to put a check here to see if 
+//we're adding to the end of the structure: [DONE, below]
+       int polyInsert = (pt == numPoints ? numPolys - 1 : GetPoly(pt));
+       for(int i=polyInsert; i<numPolys; i++)
+//     for(int i=GetPoly(pt); i<numPolys; i++)
+               polyEnd[i]++;                                                   // Bump polygons' end point
+
+       numPoints++;
+
+       delete[] x;
+       delete[] y;
+       delete[] onCurve;
+
+       x = totX, y = totY, onCurve = totOnCurve;
+}
+
+void GlyphPoints::InsertPoint(uint16 pt, const IPoint &p)
+{
+       InsertPoint(pt, p.x, p.y, p.onCurve);
+}
+
+//
+// Delete a point from the glyph
+// Note that we don't bother to reallocate anything here, just bump the
+// size counters down as needed. In the future, we'll keep track so we
+// don't have to reallocate *every* damn time a point is added...
+//
+void GlyphPoints::DeletePoint(uint16 pt)
+{
+       // Adjust polygon ends appropriately
+       uint16 poly = GetPoly(pt);
+
+       for(int i=poly; i<numPolys; i++)
+               polyEnd[i]--;
+
+//Need to check here if we're deleting the last point in the glyph or not.
+//!!! FIX !!! [DONE]
+       if (GetNumPoints(poly) == 0 && numPoints > 0)
+       {
+               numPolys--;
+
+               for(int i=poly; i<numPolys; i++)
+                       polyEnd[i] = polyEnd[i + 1];
+       }
+
+//This causes a crash becuz GetPoly() uses numPoints... !!! FIX !!! [DONE by switching poly delete & point delete]
+       // Close up the gap left by the current point
+       numPoints--;
+
+       for(int i=pt; i<numPoints; i++)
+               x[i] = x[i + 1], y[i] = y[i + 1], onCurve[i] = onCurve[i + 1];
+}
+
+uint16 GlyphPoints::GetNumPoints(void)
+{
+       return numPoints;
+}
+
+uint16 GlyphPoints::GetNumPoints(uint16 poly)
+{
+       if (poly >= numPolys)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetNumPoints(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return polyEnd[poly] - (poly == 0 ? -1 : polyEnd[poly - 1]);
+}
+
+uint16 GlyphPoints::GetNumPolys(void)
+{
+       return numPolys;
+}
+
+int GlyphPoints::GetX(uint16 pt)
+{
+       if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetX(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return x[pt];
+}
+
+int GlyphPoints::GetY(uint16 pt)
+{
+       if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetY(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return y[pt];
+}
+
+bool GlyphPoints::GetOnCurve(uint16 pt)
+{
+       if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetOnCurve(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return onCurve[pt];
+}
+
+int GlyphPoints::GetX(uint16 poly, uint16 pt)
+{
+       if (pt >= GetNumPoints(poly))
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetX(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return x[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
+}
+
+int GlyphPoints::GetY(uint16 poly, uint16 pt)
+{
+       if (pt >= GetNumPoints(poly))
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetY(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return y[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
+}
+
+bool GlyphPoints::GetOnCurve(uint16 poly, uint16 pt)
+{
+       if (pt >= GetNumPoints(poly))
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetOnCurve(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return onCurve[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
+}
+
+uint16 GlyphPoints::GetPolyEnd(uint16 poly)
+{
+       if (poly >= numPolys)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return polyEnd[poly];
+}
+
+void GlyphPoints::OffsetPoints(int xOff, int yOff)
+{
+       for(int i=0; i<numPoints; i++)
+               x[i] += xOff, y[i] += yOff;
+}
+
+//
+// Offset only a specific polygon in the glyph
+//
+void GlyphPoints::OffsetPoly(uint16 poly, int32 xOff, int32 yOff)
+{
+       if (poly >= numPolys)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       uint16 polyStart = (poly == 0 ? 0 : polyEnd[poly - 1] + 1);
+
+       for(int i=0; i<GetNumPoints(poly); i++)
+               x[polyStart + i] += xOff, y[polyStart + i] += yOff;
+}
+
+void GlyphPoints::ScalePoints(float sc)
+{
+       for(int i=0; i<numPoints; i++)
+               x[i] = (int)(((float)x[i] * sc) + 0.5f),
+               y[i] = (int)(((float)y[i] * sc) + 0.5f);
+}
+
+void GlyphPoints::SetXY(uint16 pt, int xx, int yy)
+{
+       if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: SetXY(uint16, int, int). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       x[pt] = xx, y[pt] = yy;
+}
+
+void GlyphPoints::SetOnCurve(uint16 pt, bool oc)
+{
+       if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: SetOnCurve(uint16, bool). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       onCurve[pt] = oc;
+}
+
+uint16 GlyphPoints::GetPrev(uint16 pt)
+{
+// pt = 7, polyEnd = 4, 9, 15
+       uint16 min = 0, max = numPoints - 1;
+
+       for(int i=0; i<numPolys; i++)
+       {
+               if (pt <= polyEnd[i])
+               {
+                       if (i > 0)
+                               min = polyEnd[i - 1] + 1;
+
+                       max = polyEnd[i];
+                       break;
+               }
+       }
+
+       uint16 retVal = pt - 1;
+
+       if (pt == min)
+               retVal = max;
+
+       return retVal;
+}
+
+uint16 GlyphPoints::GetNext(uint16 pt)
+{
+       uint16 min = 0, max = numPoints - 1;
+
+       for(int i=0; i<numPolys; i++)
+       {
+               if (pt <= polyEnd[i])
+               {
+                       if (i > 0)
+                               min = polyEnd[i - 1] + 1;
+
+                       max = polyEnd[i];
+                       break;
+               }
+       }
+
+       uint16 retVal = pt + 1;
+
+       if (pt == max)
+               retVal = min;
+
+       return retVal;
+}
+
+//
+// Get previous point for this polygon using wraparound.
+// Note that pt is a zero-based index!
+//
+uint16 GlyphPoints::GetPrev(uint16 poly, uint16 pt)
+{
+       return (pt == 0 ? GetNumPoints(poly) - 1 : pt - 1);
+}
+
+//
+// Get next point for this polygon using wraparound.
+// Note that pt is a zero-based index!
+//
+uint16 GlyphPoints::GetNext(uint16 poly, uint16 pt)
+{
+       return (pt == GetNumPoints(poly) - 1 ? 0 : pt + 1);
+}
+
+uint16 GlyphPoints::GetPoly(uint16 pt)
+{
+       if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetPoly(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       for(int i=0; i<numPolys; i++)
+               if (pt <= polyEnd[i])
+                       return i;
+
+       return (uint16)-1;
+}
+
+void GlyphPoints::AddNewPolyAtEnd(void)
+{
+       if (numPoints == 0)                                                     // By default, we already *have* a poly
+               return;
+
+       uint16 * newPolyEnd = new uint16[numPolys + 1];
+
+       for(uint16 i=0; i<numPolys; i++)
+               newPolyEnd[i] = polyEnd[i];
+
+       newPolyEnd[numPolys] = newPolyEnd[numPolys - 1];
+       numPolys++;
+       delete[] polyEnd;
+       polyEnd = newPolyEnd;
+}
+
index 2348d1e48f28f08aa398ba60fa78451de5495de4..2384d7cf963a05920e9e16d68269ca7fba1ad652 100755 (executable)
@@ -1,85 +1,85 @@
-//\r
-// glyphpoints.h\r
-//\r
-// by James L. Hammons\r
-//\r
-// This class encapsulates the data associated with a TrueType glyph.\r
-// Data is dynamically allocated.\r
-//\r
-\r
-#ifndef __GLYPHPOINTS_H__\r
-#define __GLYPHPOINTS_H__\r
-\r
-#include "types.h"\r
-\r
-\r
-struct IPoint\r
-{\r
-       int32 x, y;\r
-       bool onCurve;\r
-\r
-       IPoint(int32 xx=0, int32 yy=0, bool oc=true): x(xx), y(yy), onCurve(oc) {}\r
-};\r
-\r
-// Throws the following exceptions:\r
-#define GP_OUT_OF_RANGE  1\r
-\r
-class GlyphPoints\r
-{\r
-       public:\r
-//For some reason, gcc barfs here when something tries to use the copy\r
-//constructor because it gets confused between the optional arguments (which\r
-//start with an INT for cryin' out loud) and the GlyphPoints & argument. So,\r
-//Let's try making it a non-optional first param, and go from there...\r
-//Turns out the compiler barfs regardless...\r
-//Turns out the problem was that the copy ctor wasn't declared as CONST...\r
-               GlyphPoints(int nPts = 0, int nPlys = 0, int * xa = NULL, int * ya = NULL,\r
-                       bool * oca = NULL, uint16 * pa = NULL);\r
-//             GlyphPoints(void);// And now *this* is needed... Bleah!\r
-//             GlyphPoints(int nPts, int nPlys = 0, int * xa = NULL, int * ya = NULL,\r
-//                     bool * oca = NULL, uint16 * pa = NULL);\r
-               GlyphPoints(int xx, int yy, bool oc);\r
-//             GlyphPoints(GlyphPoints &);                             // Copy constructor\r
-               GlyphPoints(const GlyphPoints &);                               // Copy constructor\r
-               ~GlyphPoints();\r
-               GlyphPoints& operator=(const GlyphPoints &);\r
-               GlyphPoints operator+(const GlyphPoints &);\r
-               GlyphPoints operator+(const IPoint &);\r
-               GlyphPoints& operator+=(const IPoint &);\r
-               void InsertPoint(uint16, int, int, bool);\r
-               void InsertPoint(uint16, const IPoint &);\r
-               void DeletePoint(uint16);\r
-               uint16 GetNumPoints(void);\r
-               uint16 GetNumPoints(uint16);\r
-               uint16 GetNumPolys(void);\r
-               int GetX(uint16);\r
-               int GetY(uint16);\r
-               bool GetOnCurve(uint16);\r
-               int GetX(uint16, uint16);\r
-               int GetY(uint16, uint16);\r
-               bool GetOnCurve(uint16, uint16);\r
-               uint16 GetPolyEnd(uint16);\r
-               void OffsetPoints(int, int);\r
-               void OffsetPoly(uint16, int32, int32);\r
-               void ScalePoints(float);\r
-               void SetXY(uint16, int, int);\r
-               void SetOnCurve(uint16, bool);\r
-               uint16 GetPrev(uint16);\r
-               uint16 GetNext(uint16);\r
-               uint16 GetPrev(uint16, uint16);\r
-               uint16 GetNext(uint16, uint16);\r
-               uint16 GetPoly(uint16);\r
-               void AddNewPolyAtEnd(void);\r
-\r
-       private:\r
-               void AllocateAndCopy(int, int, int *, int *, bool *, uint16 *);\r
-\r
-       private:\r
-               int numPoints, numPolys;\r
-               int * x, * y;\r
-               bool * onCurve;\r
-               uint16 * polyEnd;\r
-               uint16 pointsAllocated, polysAllocated;\r
-};\r
-\r
-#endif // __GLYPHPOINTS_H__\r
+//
+// glyphpoints.h
+//
+// by James L. Hammons
+//
+// This class encapsulates the data associated with a TrueType glyph.
+// Data is dynamically allocated.
+//
+
+#ifndef __GLYPHPOINTS_H__
+#define __GLYPHPOINTS_H__
+
+#include "types.h"
+
+
+struct IPoint
+{
+       int32 x, y;
+       bool onCurve;
+
+       IPoint(int32 xx=0, int32 yy=0, bool oc=true): x(xx), y(yy), onCurve(oc) {}
+};
+
+// Throws the following exceptions:
+#define GP_OUT_OF_RANGE  1
+
+class GlyphPoints
+{
+       public:
+//For some reason, gcc barfs here when something tries to use the copy
+//constructor because it gets confused between the optional arguments (which
+//start with an INT for cryin' out loud) and the GlyphPoints & argument. So,
+//Let's try making it a non-optional first param, and go from there...
+//Turns out the compiler barfs regardless...
+//Turns out the problem was that the copy ctor wasn't declared as CONST...
+               GlyphPoints(int nPts = 0, int nPlys = 0, int * xa = NULL, int * ya = NULL,
+                       bool * oca = NULL, uint16 * pa = NULL);
+//             GlyphPoints(void);// And now *this* is needed... Bleah!
+//             GlyphPoints(int nPts, int nPlys = 0, int * xa = NULL, int * ya = NULL,
+//                     bool * oca = NULL, uint16 * pa = NULL);
+               GlyphPoints(int xx, int yy, bool oc);
+//             GlyphPoints(GlyphPoints &);                             // Copy constructor
+               GlyphPoints(const GlyphPoints &);                               // Copy constructor
+               ~GlyphPoints();
+               GlyphPoints& operator=(const GlyphPoints &);
+               GlyphPoints operator+(const GlyphPoints &);
+               GlyphPoints operator+(const IPoint &);
+               GlyphPoints& operator+=(const IPoint &);
+               void InsertPoint(uint16, int, int, bool);
+               void InsertPoint(uint16, const IPoint &);
+               void DeletePoint(uint16);
+               uint16 GetNumPoints(void);
+               uint16 GetNumPoints(uint16);
+               uint16 GetNumPolys(void);
+               int GetX(uint16);
+               int GetY(uint16);
+               bool GetOnCurve(uint16);
+               int GetX(uint16, uint16);
+               int GetY(uint16, uint16);
+               bool GetOnCurve(uint16, uint16);
+               uint16 GetPolyEnd(uint16);
+               void OffsetPoints(int, int);
+               void OffsetPoly(uint16, int32, int32);
+               void ScalePoints(float);
+               void SetXY(uint16, int, int);
+               void SetOnCurve(uint16, bool);
+               uint16 GetPrev(uint16);
+               uint16 GetNext(uint16);
+               uint16 GetPrev(uint16, uint16);
+               uint16 GetNext(uint16, uint16);
+               uint16 GetPoly(uint16);
+               void AddNewPolyAtEnd(void);
+
+       private:
+               void AllocateAndCopy(int, int, int *, int *, bool *, uint16 *);
+
+       private:
+               int numPoints, numPolys;
+               int * x, * y;
+               bool * onCurve;
+               uint16 * polyEnd;
+               uint16 pointsAllocated, polysAllocated;
+};
+
+#endif // __GLYPHPOINTS_H__
index 9802347b713ae289496f3a2eb9ab7e8a3f14d4b4..6eb84a23770a39552862be9d63b6ee8e6283daa7 100755 (executable)
-//\r
-// Graphics primitives\r
-//\r
-// Various graphic functions that are slightly more complex than those that\r
-// come with various widget libraries.\r
-//\r
-// by James L. Hammons\r
-// (C) 2005 Underground Software\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  -------------------------------------------------------------\r
-// JLH  03/14/1998  Created this file\r
-// JLH  01/20/2005  Converted to use wxWidgets\r
-// JLH  08/30/2008  Repurposed file to handle more than just bezier curves\r
-//\r
-\r
-#include "graphicprimitives.h"\r
-\r
-double abs(double n)                                                   // Helper function\r
-{\r
-       return (n < 0 ? -n : n);\r
-}\r
-\r
-//\r
-// This function takes three points and draws a curve using a second order\r
-// Bezier function.\r
-//\r
-void Bezier(wxDC &dc, point p1, point p2, point p3)\r
-{\r
-       double step = abs(p1.x - p3.x), tmp = abs(p1.y - p3.y);\r
-       step = (tmp > step ? tmp : step);                       // Get the larger of the two...\r
-       step = (step > 0 ? 1/step : 1);                         // & convert to valid step value\r
-\r
-       wxCoord prevX = (wxCoord)p1.x, prevY = (wxCoord)p1.y;\r
-\r
-       for(double u=0; u<=1; u+=step)\r
-       {\r
-               double _2u = 2*u, _uu = u*u, _2uu = 2*_uu;\r
-               double x = (p1.x * (1 - _2u + _uu)) + (p2.x * (_2u - _2uu)) + (p3.x * _uu);\r
-               double y = (p1.y * (1 - _2u + _uu)) + (p2.y * (_2u - _2uu)) + (p3.y * _uu);\r
-\r
-               dc.DrawLine(prevX, prevY, (wxCoord)x, (wxCoord)y);\r
-               prevX = (wxCoord)x, prevY = (wxCoord)y;\r
-       }\r
-\r
-       dc.DrawLine(prevX, prevY, (wxCoord)p3.x, (wxCoord)p3.y);\r
-}\r
-\r
-//\r
-// Draw a round dot (5x5, centered on [x, y])\r
-//\r
-void DrawRoundDot(wxDC &dc, int32 x, int32 y)\r
-{\r
-       wxPoint pt[8];\r
-\r
-       pt[0].x = x - 1, pt[0].y = y - 2;\r
-       pt[1].x = x + 1, pt[1].y = y - 2;\r
-       pt[2].x = x + 2, pt[2].y = y - 1;\r
-       pt[3].x = x + 2, pt[3].y = y + 1;\r
-       pt[4].x = x + 1, pt[4].y = y + 2;\r
-       pt[5].x = x - 1, pt[5].y = y + 2;\r
-       pt[6].x = x - 2, pt[6].y = y + 1;\r
-       pt[7].x = x - 2, pt[7].y = y - 1;\r
-\r
-       dc.DrawPolygon(8, pt);\r
-}\r
-\r
-//\r
-// Draw a sqaure dot (5x5, centered on [x, y])\r
-//\r
-void DrawSquareDot(wxDC &dc, int32 x, int32 y)\r
-{\r
-       wxPoint pt[4];\r
-\r
-       pt[0].x = x - 2, pt[0].y = y - 2;\r
-       pt[1].x = x + 2, pt[1].y = y - 2;\r
-       pt[2].x = x + 2, pt[2].y = y + 2;\r
-       pt[3].x = x - 2, pt[3].y = y + 2;\r
-\r
-       dc.DrawPolygon(4, pt);\r
-}\r
-\r
-//\r
-// Draw a sqaure dot (nxn, centered on [x, y])\r
-//\r
-void DrawSquareDotN(wxDC &dc, int32 x, int32 y, uint32 n)\r
-{\r
-       wxPoint pt[4];\r
-       uint32 offset = (n - 1) / 2;\r
-\r
-       pt[0].x = x - offset, pt[0].y = y - offset;\r
-       pt[1].x = x + offset, pt[1].y = y - offset;\r
-       pt[2].x = x + offset, pt[2].y = y + offset;\r
-       pt[3].x = x - offset, pt[3].y = y + offset;\r
-\r
-       dc.DrawPolygon(4, pt);\r
-}\r
-\r
-//\r
-// Draw a round dot (nxn, centered on [x, y])\r
-//\r
-void DrawRoundDotN(wxDC &dc, int32 x, int32 y, uint32 n)\r
-{\r
-       dc.DrawCircle(x, y, (n / 2) + 1);\r
-}\r
+//
+// Graphics primitives
+//
+// Various graphic functions that are slightly more complex than those that
+// come with various widget libraries.
+//
+// by James L. Hammons
+// (C) 2005 Underground Software
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  03/14/1998  Created this file
+// JLH  01/20/2005  Converted to use wxWidgets
+// JLH  08/30/2008  Repurposed file to handle more than just bezier curves
+//
+
+#include "graphicprimitives.h"
+
+double abs(double n)                                                   // Helper function
+{
+       return (n < 0 ? -n : n);
+}
+
+//
+// This function takes three points and draws a curve using a second order
+// Bezier function.
+//
+void Bezier(wxDC &dc, point p1, point p2, point p3)
+{
+       double step = abs(p1.x - p3.x), tmp = abs(p1.y - p3.y);
+       step = (tmp > step ? tmp : step);                       // Get the larger of the two...
+       step = (step > 0 ? 1/step : 1);                         // & convert to valid step value
+
+       wxCoord prevX = (wxCoord)p1.x, prevY = (wxCoord)p1.y;
+
+       for(double u=0; u<=1; u+=step)
+       {
+               double _2u = 2*u, _uu = u*u, _2uu = 2*_uu;
+               double x = (p1.x * (1 - _2u + _uu)) + (p2.x * (_2u - _2uu)) + (p3.x * _uu);
+               double y = (p1.y * (1 - _2u + _uu)) + (p2.y * (_2u - _2uu)) + (p3.y * _uu);
+
+               dc.DrawLine(prevX, prevY, (wxCoord)x, (wxCoord)y);
+               prevX = (wxCoord)x, prevY = (wxCoord)y;
+       }
+
+       dc.DrawLine(prevX, prevY, (wxCoord)p3.x, (wxCoord)p3.y);
+}
+
+//
+// Draw a round dot (5x5, centered on [x, y])
+//
+void DrawRoundDot(wxDC &dc, int32 x, int32 y)
+{
+       wxPoint pt[8];
+
+       pt[0].x = x - 1, pt[0].y = y - 2;
+       pt[1].x = x + 1, pt[1].y = y - 2;
+       pt[2].x = x + 2, pt[2].y = y - 1;
+       pt[3].x = x + 2, pt[3].y = y + 1;
+       pt[4].x = x + 1, pt[4].y = y + 2;
+       pt[5].x = x - 1, pt[5].y = y + 2;
+       pt[6].x = x - 2, pt[6].y = y + 1;
+       pt[7].x = x - 2, pt[7].y = y - 1;
+
+       dc.DrawPolygon(8, pt);
+}
+
+//
+// Draw a sqaure dot (5x5, centered on [x, y])
+//
+void DrawSquareDot(wxDC &dc, int32 x, int32 y)
+{
+       wxPoint pt[4];
+
+       pt[0].x = x - 2, pt[0].y = y - 2;
+       pt[1].x = x + 2, pt[1].y = y - 2;
+       pt[2].x = x + 2, pt[2].y = y + 2;
+       pt[3].x = x - 2, pt[3].y = y + 2;
+
+       dc.DrawPolygon(4, pt);
+}
+
+//
+// Draw a sqaure dot (nxn, centered on [x, y])
+//
+void DrawSquareDotN(wxDC &dc, int32 x, int32 y, uint32 n)
+{
+       wxPoint pt[4];
+       uint32 offset = (n - 1) / 2;
+
+       pt[0].x = x - offset, pt[0].y = y - offset;
+       pt[1].x = x + offset, pt[1].y = y - offset;
+       pt[2].x = x + offset, pt[2].y = y + offset;
+       pt[3].x = x - offset, pt[3].y = y + offset;
+
+       dc.DrawPolygon(4, pt);
+}
+
+//
+// Draw a round dot (nxn, centered on [x, y])
+//
+void DrawRoundDotN(wxDC &dc, int32 x, int32 y, uint32 n)
+{
+       dc.DrawCircle(x, y, (n / 2) + 1);
+}
index dbc7a116f5a6f76867ed84b17fb95e0e56838d02..81e15abf8da68afecde87fafbda8549de4d0e0ea 100755 (executable)
@@ -1,27 +1,27 @@
-//\r
-// Graphics primitives\r
-//\r
-// Various graphic functions that are slightly more complex than those that\r
-// come with various widget libraries.\r
-//\r
-\r
-#ifndef __GRAPHICPRIMITIVES_H__\r
-#define __GRAPHICPRIMITIVES_H__\r
-\r
-#include <wx/wx.h>                                                             // For device context\r
-#include "types.h"                                                             // For int32\r
-\r
-struct point\r
-{\r
-       float x, y;\r
-\r
-       point(float xx = 0, float yy = 0): x(xx), y(yy) {}\r
-};\r
-\r
-void Bezier(wxDC &, point, point, point);\r
-void DrawRoundDot(wxDC &, int32, int32);\r
-void DrawSquareDot(wxDC &, int32, int32);\r
-void DrawRoundDotN(wxDC &, int32, int32, uint32);\r
-void DrawSquareDotN(wxDC &, int32, int32, uint32);\r
-\r
-#endif // __GRAPHICPRIMITIVES_H__\r
+//
+// Graphics primitives
+//
+// Various graphic functions that are slightly more complex than those that
+// come with various widget libraries.
+//
+
+#ifndef __GRAPHICPRIMITIVES_H__
+#define __GRAPHICPRIMITIVES_H__
+
+#include <wx/wx.h>                                                             // For device context
+#include "types.h"                                                             // For int32
+
+struct point
+{
+       float x, y;
+
+       point(float xx = 0, float yy = 0): x(xx), y(yy) {}
+};
+
+void Bezier(wxDC &, point, point, point);
+void DrawRoundDot(wxDC &, int32, int32);
+void DrawSquareDot(wxDC &, int32, int32);
+void DrawRoundDotN(wxDC &, int32, int32, uint32);
+void DrawSquareDotN(wxDC &, int32, int32, uint32);
+
+#endif // __GRAPHICPRIMITIVES_H__
index da0501f6e863cb1d75fe0914c0b0cf8067a0c1a3..b202fcb72277ee08f92d0d9f9a6007236d8f05ab 100755 (executable)
-//\r
-// A generic list class using a circular singly linked list\r
-// by James L. Hammons\r
-// (C) 2004 Underground Software\r
-//\r
-// Based upon work I did for CS240 Project 5 at Cal Poly Pomona for Dr. Bruce Hillam.\r
-// Hello Dr. Hillam! :-)\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  -------------------------------------------------------------\r
-// JLH  08/30/1999  Created this file\r
-// JLH  05/11/2004  Cleaned up a few things in the implementation\r
-//\r
-\r
-\r
-// Some exception constants\r
-\r
-#define LIST_EMPTY             1\r
-#define OUT_OF_RANGE   2\r
-\r
-template <class T> class List;                                 // Forward declaration...\r
-template <class T> class Node\r
-{\r
-       friend class List<T>;\r
-\r
-       public:\r
-               Node(void): next(NULL) {}\r
-               Node(const T d, Node * ptr = NULL): data(d), next(ptr) {}\r
-\r
-       private:\r
-               T data;\r
-               Node * next;\r
-};\r
-\r
-template <class T> class List      \r
-{\r
-       // This class implements the following exceptions:\r
-       // LIST_EMPTY is thrown if you attempt to remove an object from an empty list.\r
-       // OUT_OF_RANGE is thrown if you attempt to Add or Get from a position that\r
-       // does not exist for the list.\r
-\r
-       private:\r
-               Node<T> * last;\r
-               int length;\r
-\r
-       public:\r
-               List(void);\r
-               ~List();\r
-               bool operator==(List &l);\r
-               void AddAtFront(T data);\r
-               void AddAtRear(T data);\r
-               void AddAtPosition(int pos, T data);\r
-               T GetFront(void);\r
-               T GetRear(void);\r
-               T GetPosition(int pos);\r
-               T PeekFront(void);\r
-               T PeekRear(void);\r
-               T PeekPosition(int pos);\r
-               bool IsEmpty(void);\r
-               int Length(void);\r
-};\r
-\r
-//\r
-// List class implementation\r
-//\r
-template <class T> List<T>::List(void)\r
-{\r
-       last = NULL;\r
-       length = 0;\r
-}\r
-\r
-template <class T> List<T>::~List()\r
-{\r
-       while (length)                                                          // Destroy all nodes that were created...\r
-       {\r
-               Node<T> * tmp = last;\r
-               last = last->next;\r
-               delete tmp;\r
-               length--;\r
-       }\r
-}\r
-\r
-template <class T> bool List<T>::operator==(List &l)\r
-{\r
-       if (Length() != l.Length())\r
-               return false;\r
-\r
-       Node<T> * ptr1 = last->next, * ptr2 = l.last->next;\r
-\r
-       do\r
-       {\r
-               if (ptr1->data != ptr2->data)\r
-                       return false;\r
-\r
-               ptr1 = ptr1->next, ptr2 = ptr2->next;\r
-       }\r
-       while (ptr1 != last);\r
-\r
-       return true;\r
-}\r
-\r
-template <class T> void List<T>::AddAtFront(T data)\r
-{\r
-       Node<T> * newNode = new Node<T>(data);\r
-\r
-       if (last == NULL)                                                       // i.e., the list is empty...\r
-               last = newNode->next = newNode;\r
-       else\r
-       {\r
-               newNode->next = last->next;\r
-               last->next = newNode;\r
-       }\r
-\r
-       length++;\r
-}\r
-\r
-template <class T> void List<T>::AddAtRear(T data)\r
-{\r
-       Node<T> * newNode = new Node<T>(data);\r
-\r
-       if (last == NULL)                                                       // i.e., the list is empty...\r
-               last = newNode->next = newNode;\r
-       else\r
-       {\r
-               newNode->next = last->next;\r
-               last->next = newNode;\r
-               last = newNode;\r
-       }\r
-\r
-       length++;\r
-}\r
-\r
-template <class T> void List<T>::AddAtPosition(int pos, T data)\r
-{\r
-       if ((pos < 1) || (pos > length))\r
-               throw OUT_OF_RANGE;\r
-\r
-       if (pos == 1)\r
-               AddAtFront(data);                                               // Why reinvent the wheel?\r
-\r
-       if (pos == length)\r
-               AddAtRear(data);\r
-\r
-       Node<T> * newNode = new Node<T>(data), * tmp = last;\r
-\r
-       for(int i=1; i!=pos; i++)                                       // Make tmp point to node ahead of add position\r
-               tmp = tmp->next;\r
-\r
-       newNode->next = tmp->next;\r
-       tmp->next = newNode;\r
-\r
-       length++;\r
-}\r
-\r
-template <class T> T List<T>::GetFront(void)\r
-{\r
-       if (IsEmpty())\r
-               throw LIST_EMPTY;\r
-\r
-       T retVal = last->next->data;\r
-       Node<T> * ptr = last->next;\r
-\r
-       if (length == 1)\r
-               last = NULL;\r
-       else\r
-               last->next = last->next->next;\r
-\r
-       delete ptr;\r
-       length--;\r
-\r
-       return retVal;\r
-}\r
-\r
-template <class T> T List<T>::GetRear(void)\r
-{\r
-       if (IsEmpty())\r
-               throw LIST_EMPTY;\r
-\r
-       T retVal = last->data;\r
-       Node<T> * ptr = last;\r
-\r
-       if (length == 1)\r
-       {\r
-               delete last;\r
-               last = NULL;\r
-       }\r
-       else\r
-       {\r
-               while (ptr->next != last)\r
-                       ptr = ptr->next;\r
-\r
-               ptr->next = ptr->next->next;\r
-               delete last;\r
-               last = ptr;  \r
-       }\r
-\r
-       length--;\r
-\r
-       return retVal;\r
-}\r
-\r
-template <class T> T List<T>::GetPosition(int pos)\r
-{\r
-       if (IsEmpty())\r
-               throw LIST_EMPTY;\r
-\r
-       if ((pos < 1) || (pos > length))\r
-               throw OUT_OF_RANGE;\r
-\r
-       if (pos == 1)\r
-               return GetFront();                                              // Why reinvent the wheel?\r
-\r
-       if (pos == length)\r
-               return GetRear();\r
-\r
-       Node<T> * tmp = last;\r
-\r
-       for(int i=1; i!=pos; i++)                                       // Make tmp point to node ahead of del position\r
-               tmp = tmp->next;\r
-\r
-       Node<T> * nodeToDelete = tmp->next;\r
-               T retVal = nodeToDelete->data;\r
-\r
-       tmp->next = tmp->next->next;\r
-       delete nodeToDelete;\r
-\r
-       length--;\r
-       return retVal;\r
-}\r
-\r
-template <class T> T List<T>::PeekFront(void)\r
-{\r
-       if (IsEmpty())\r
-               throw LIST_EMPTY;\r
-\r
-       return last->next->data;\r
-}\r
-\r
-template <class T> T List<T>::PeekRear(void)\r
-{\r
-       if (IsEmpty())\r
-               throw LIST_EMPTY;\r
-\r
-       return last->data;\r
-}\r
-\r
-template <class T> T List<T>::PeekPosition(int pos)\r
-{\r
-       if (IsEmpty())\r
-               throw LIST_EMPTY;\r
-\r
-       if ((pos < 1) || (pos > length))\r
-               throw OUT_OF_RANGE;\r
-\r
-       if (pos == 1)\r
-               return PeekFront();                                             // Why reinvent the wheel?\r
-\r
-       if (pos == length)\r
-               return PeekRear();\r
-\r
-       Node<T> * tmp = last;\r
-\r
-       for(int i=1; i!=pos; i++)\r
-               tmp = tmp->next;\r
-\r
-       return tmp->next->data;\r
-}\r
-\r
-template <class T> inline bool List<T>::IsEmpty(void)\r
-{\r
-       return (bool)(length == 0);\r
-}\r
-\r
-template <class T> inline int List<T>::Length(void)\r
-{\r
-       return length;\r
-}\r
+//
+// A generic list class using a circular singly linked list
+// by James L. Hammons
+// (C) 2004 Underground Software
+//
+// Based upon work I did for CS240 Project 5 at Cal Poly Pomona for Dr. Bruce Hillam.
+// Hello Dr. Hillam! :-)
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  08/30/1999  Created this file
+// JLH  05/11/2004  Cleaned up a few things in the implementation
+//
+
+
+// Some exception constants
+
+#define LIST_EMPTY             1
+#define OUT_OF_RANGE   2
+
+template <class T> class List;                                 // Forward declaration...
+template <class T> class Node
+{
+       friend class List<T>;
+
+       public:
+               Node(void): next(NULL) {}
+               Node(const T d, Node * ptr = NULL): data(d), next(ptr) {}
+
+       private:
+               T data;
+               Node * next;
+};
+
+template <class T> class List      
+{
+       // This class implements the following exceptions:
+       // LIST_EMPTY is thrown if you attempt to remove an object from an empty list.
+       // OUT_OF_RANGE is thrown if you attempt to Add or Get from a position that
+       // does not exist for the list.
+
+       private:
+               Node<T> * last;
+               int length;
+
+       public:
+               List(void);
+               ~List();
+               bool operator==(List &l);
+               void AddAtFront(T data);
+               void AddAtRear(T data);
+               void AddAtPosition(int pos, T data);
+               T GetFront(void);
+               T GetRear(void);
+               T GetPosition(int pos);
+               T PeekFront(void);
+               T PeekRear(void);
+               T PeekPosition(int pos);
+               bool IsEmpty(void);
+               int Length(void);
+};
+
+//
+// List class implementation
+//
+template <class T> List<T>::List(void)
+{
+       last = NULL;
+       length = 0;
+}
+
+template <class T> List<T>::~List()
+{
+       while (length)                                                          // Destroy all nodes that were created...
+       {
+               Node<T> * tmp = last;
+               last = last->next;
+               delete tmp;
+               length--;
+       }
+}
+
+template <class T> bool List<T>::operator==(List &l)
+{
+       if (Length() != l.Length())
+               return false;
+
+       Node<T> * ptr1 = last->next, * ptr2 = l.last->next;
+
+       do
+       {
+               if (ptr1->data != ptr2->data)
+                       return false;
+
+               ptr1 = ptr1->next, ptr2 = ptr2->next;
+       }
+       while (ptr1 != last);
+
+       return true;
+}
+
+template <class T> void List<T>::AddAtFront(T data)
+{
+       Node<T> * newNode = new Node<T>(data);
+
+       if (last == NULL)                                                       // i.e., the list is empty...
+               last = newNode->next = newNode;
+       else
+       {
+               newNode->next = last->next;
+               last->next = newNode;
+       }
+
+       length++;
+}
+
+template <class T> void List<T>::AddAtRear(T data)
+{
+       Node<T> * newNode = new Node<T>(data);
+
+       if (last == NULL)                                                       // i.e., the list is empty...
+               last = newNode->next = newNode;
+       else
+       {
+               newNode->next = last->next;
+               last->next = newNode;
+               last = newNode;
+       }
+
+       length++;
+}
+
+template <class T> void List<T>::AddAtPosition(int pos, T data)
+{
+       if ((pos < 1) || (pos > length))
+               throw OUT_OF_RANGE;
+
+       if (pos == 1)
+               AddAtFront(data);                                               // Why reinvent the wheel?
+
+       if (pos == length)
+               AddAtRear(data);
+
+       Node<T> * newNode = new Node<T>(data), * tmp = last;
+
+       for(int i=1; i!=pos; i++)                                       // Make tmp point to node ahead of add position
+               tmp = tmp->next;
+
+       newNode->next = tmp->next;
+       tmp->next = newNode;
+
+       length++;
+}
+
+template <class T> T List<T>::GetFront(void)
+{
+       if (IsEmpty())
+               throw LIST_EMPTY;
+
+       T retVal = last->next->data;
+       Node<T> * ptr = last->next;
+
+       if (length == 1)
+               last = NULL;
+       else
+               last->next = last->next->next;
+
+       delete ptr;
+       length--;
+
+       return retVal;
+}
+
+template <class T> T List<T>::GetRear(void)
+{
+       if (IsEmpty())
+               throw LIST_EMPTY;
+
+       T retVal = last->data;
+       Node<T> * ptr = last;
+
+       if (length == 1)
+       {
+               delete last;
+               last = NULL;
+       }
+       else
+       {
+               while (ptr->next != last)
+                       ptr = ptr->next;
+
+               ptr->next = ptr->next->next;
+               delete last;
+               last = ptr;  
+       }
+
+       length--;
+
+       return retVal;
+}
+
+template <class T> T List<T>::GetPosition(int pos)
+{
+       if (IsEmpty())
+               throw LIST_EMPTY;
+
+       if ((pos < 1) || (pos > length))
+               throw OUT_OF_RANGE;
+
+       if (pos == 1)
+               return GetFront();                                              // Why reinvent the wheel?
+
+       if (pos == length)
+               return GetRear();
+
+       Node<T> * tmp = last;
+
+       for(int i=1; i!=pos; i++)                                       // Make tmp point to node ahead of del position
+               tmp = tmp->next;
+
+       Node<T> * nodeToDelete = tmp->next;
+               T retVal = nodeToDelete->data;
+
+       tmp->next = tmp->next->next;
+       delete nodeToDelete;
+
+       length--;
+       return retVal;
+}
+
+template <class T> T List<T>::PeekFront(void)
+{
+       if (IsEmpty())
+               throw LIST_EMPTY;
+
+       return last->next->data;
+}
+
+template <class T> T List<T>::PeekRear(void)
+{
+       if (IsEmpty())
+               throw LIST_EMPTY;
+
+       return last->data;
+}
+
+template <class T> T List<T>::PeekPosition(int pos)
+{
+       if (IsEmpty())
+               throw LIST_EMPTY;
+
+       if ((pos < 1) || (pos > length))
+               throw OUT_OF_RANGE;
+
+       if (pos == 1)
+               return PeekFront();                                             // Why reinvent the wheel?
+
+       if (pos == length)
+               return PeekRear();
+
+       Node<T> * tmp = last;
+
+       for(int i=1; i!=pos; i++)
+               tmp = tmp->next;
+
+       return tmp->next->data;
+}
+
+template <class T> inline bool List<T>::IsEmpty(void)
+{
+       return (bool)(length == 0);
+}
+
+template <class T> inline int List<T>::Length(void)
+{
+       return length;
+}
index cbf3862727ff7f93fb487fe51aa2b0ec109a6403..576207acb3bbb5e6b500cfeea2718c1e39b75e37 100755 (executable)
@@ -1,94 +1,94 @@
-//\r
-// REGISTRY.CPP - Win32 support file\r
-// by James L. Hammons\r
-// (C) 2002 Underground Software\r
-//\r
-//   JLH = James Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  ------------------------------------------------------------\r
-// JLH  05/16/2002  Created this file\r
-// JLH  12/10/2002  Updated InitINIFile to take a parameter so that you can open\r
-//                  an .INI file that doesn't belong to the current module\r
-//\r
-// STILL TO BE DONE:\r
-//\r
-// - Convert to wxWidgets...\r
-//\r
-\r
-#warning This file not yet converted to wxWidgets!!!\r
-\r
-#if 0\r
-#include <windows.h>\r
-#include "registry.h"\r
-\r
-// Local data\r
-\r
-static char INIPath[MAX_PATH];\r
-static char str[4096];\r
-\r
-//\r
-// Initialize the application .INI file\r
-// Returns TRUE if succesful, FALSE otherwise...\r
-//\r
-void InitINIFile(char * path/*= NULL*/)\r
-{\r
-       if (!GetModuleFileName(NULL, INIPath, MAX_PATH))\r
-               return;\r
-\r
-       if (path == NULL)\r
-       {\r
-               int len = lstrlen(INIPath);\r
-               lstrcpy(INIPath + len - 4, ".ini");\r
-       }\r
-       else\r
-       {\r
-               for(int i=lstrlen(INIPath); i>=0; i--)\r
-               {\r
-                       if (INIPath[i] == '\\')\r
-                       {\r
-                               lstrcpy(INIPath + i + 1, path);\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-//\r
-// Write an int value to our .INI file\r
-//\r
-void SetINIInt(char * section, char * entry, int32 value)\r
-{\r
-       const char fmtStr[] = "%d";\r
-       char strVal[20];\r
-\r
-       wsprintf(strVal, fmtStr, value);\r
-       WritePrivateProfileString(section, entry, strVal, INIPath);\r
-}\r
-\r
-//\r
-// Write a string value to our .INI file\r
-//\r
-void SetINIString(char * section, char * entry, char * value)\r
-{\r
-       WritePrivateProfileString(section, entry, value, INIPath);\r
-}\r
-\r
-//\r
-// Get an int value from our .INI file\r
-//\r
-int32 GetINIInt(char * section, char * entry, int32 _default)\r
-{\r
-       return GetPrivateProfileInt(section, entry, _default, INIPath);\r
-}\r
-\r
-//\r
-// Get a string value from our .INI file\r
-//\r
-const char * GetINIString(char * section, char * entry, char * _default)\r
-{\r
-       GetPrivateProfileString(section, entry, _default, str, 4096, INIPath);\r
-\r
-       return str;\r
-}\r
-#endif\r
+//
+// REGISTRY.CPP - Win32 support file
+// by James L. Hammons
+// (C) 2002 Underground Software
+//
+//   JLH = James Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  ------------------------------------------------------------
+// JLH  05/16/2002  Created this file
+// JLH  12/10/2002  Updated InitINIFile to take a parameter so that you can open
+//                  an .INI file that doesn't belong to the current module
+//
+// STILL TO BE DONE:
+//
+// - Convert to wxWidgets...
+//
+
+#warning This file not yet converted to wxWidgets!!!
+
+#if 0
+#include <windows.h>
+#include "registry.h"
+
+// Local data
+
+static char INIPath[MAX_PATH];
+static char str[4096];
+
+//
+// Initialize the application .INI file
+// Returns TRUE if succesful, FALSE otherwise...
+//
+void InitINIFile(char * path/*= NULL*/)
+{
+       if (!GetModuleFileName(NULL, INIPath, MAX_PATH))
+               return;
+
+       if (path == NULL)
+       {
+               int len = lstrlen(INIPath);
+               lstrcpy(INIPath + len - 4, ".ini");
+       }
+       else
+       {
+               for(int i=lstrlen(INIPath); i>=0; i--)
+               {
+                       if (INIPath[i] == '\\')
+                       {
+                               lstrcpy(INIPath + i + 1, path);
+                               break;
+                       }
+               }
+       }
+}
+
+//
+// Write an int value to our .INI file
+//
+void SetINIInt(char * section, char * entry, int32 value)
+{
+       const char fmtStr[] = "%d";
+       char strVal[20];
+
+       wsprintf(strVal, fmtStr, value);
+       WritePrivateProfileString(section, entry, strVal, INIPath);
+}
+
+//
+// Write a string value to our .INI file
+//
+void SetINIString(char * section, char * entry, char * value)
+{
+       WritePrivateProfileString(section, entry, value, INIPath);
+}
+
+//
+// Get an int value from our .INI file
+//
+int32 GetINIInt(char * section, char * entry, int32 _default)
+{
+       return GetPrivateProfileInt(section, entry, _default, INIPath);
+}
+
+//
+// Get a string value from our .INI file
+//
+const char * GetINIString(char * section, char * entry, char * _default)
+{
+       GetPrivateProfileString(section, entry, _default, str, 4096, INIPath);
+
+       return str;
+}
+#endif
index 73843415fef02d35f160ffd61c2b72e8ee58cf90..526713b5cdd3f79b37954c545832c8b21ef85143 100755 (executable)
@@ -1,22 +1,22 @@
-//\r
-// REGISTRY.H - Win32 support file header\r
-// by James L. Hammons\r
-// (C) 2002 Underground Software\r
-//\r
-//   JLH = James Hammons <jlhamm@acm.org>\r
-//\r
-\r
-#ifndef __REGISTRY_H__\r
-#define __REGISTRY_H__\r
-\r
-#include "types.h"\r
-\r
-// Function prototypes\r
-\r
-void InitINIFile(char * path = NULL);\r
-void SetINIInt(char *, char *, int32);\r
-void SetINIString(char *, char *, char *);\r
-int32 GetINIInt(char *, char *, int32);\r
-const char * GetINIString(char *, char *, char *);\r
-\r
-#endif // __REGISTRY_H__\r
+//
+// REGISTRY.H - Win32 support file header
+// by James L. Hammons
+// (C) 2002 Underground Software
+//
+//   JLH = James Hammons <jlhamm@acm.org>
+//
+
+#ifndef __REGISTRY_H__
+#define __REGISTRY_H__
+
+#include "types.h"
+
+// Function prototypes
+
+void InitINIFile(char * path = NULL);
+void SetINIInt(char *, char *, int32);
+void SetINIString(char *, char *, char *);
+int32 GetINIInt(char *, char *, int32);
+const char * GetINIString(char *, char *, char *);
+
+#endif // __REGISTRY_H__
index 453296490827ea2a41e35383e94475b3e6da21a7..80f90e429a5edf8b1ff0c14841808cfc2325396a 100755 (executable)
@@ -1,95 +1,95 @@
-//\r
-// TOOLWINDOW.CPP - Tool Palette window\r
-// by James L. Hammons\r
-// (C) 2008 Underground Software\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  -------------------------------------------------------------\r
-// JLH  08/28/2008  Created this file\r
-//\r
-\r
-// FIXED:\r
-//\r
-// STILL TO BE DONE:\r
-//\r
-//\r
-\r
-// Uncomment this for debugging...\r
-#define DEBUG\r
-#define DEBUGFOO            // Various tool debugging...\r
-#define DEBUGTP                                // Toolpalette debugging...\r
-\r
-#include "toolwindow.h"\r
-#include "types.h"\r
-\r
-// Pixmap resources\r
-\r
-#include "res/toolpal1.xpm"                                            // Docs say this is portable... Let's see!\r
-\r
-\r
-BEGIN_EVENT_TABLE(ToolWindow, wxFrame)\r
-       EVT_PAINT(ToolWindow::OnPaint)\r
-END_EVENT_TABLE()\r
-\r
-\r
-ToolWindow::ToolWindow(wxFrame * parent, const wxString &title, const wxPoint &pos,\r
-       const wxSize &size, long style): wxFrame(parent, -1, title, pos, size, style),\r
-       bmp(NULL), prevTool(TOOLNone)\r
-{\r
-       bmp = new wxBitmap(toolpal1_xpm);\r
-\r
-       // Set up sizes\r
-\r
-       sizeTPBM.x = bmp->GetWidth(), sizeTPBM.y = bmp->GetHeight();\r
-       sizeStamp.x = sizeTPBM.x / 4, sizeStamp.y = sizeTPBM.y / 2;\r
-\r
-       SetSize(0, 0, sizeTPBM.x, sizeTPBM.y);\r
-       Show(false);\r
-}\r
-\r
-ToolWindow::~ToolWindow()\r
-{\r
-       if (bmp)\r
-               delete bmp;\r
-}\r
-\r
-void ToolWindow::OnPaint(wxPaintEvent &e)\r
-{\r
-       wxPaintDC dc(this);\r
-\r
-       wxMemoryDC memDC;\r
-       memDC.SelectObject(*bmp);\r
-       dc.Blit(0, 0, sizeTPBM.x, sizeTPBM.y, &memDC, 0, 0, wxCOPY);\r
-\r
-       if (prevTool != -1)\r
-       {\r
-           //need ul corner of bitmap, ul corner of dest, width/height\r
-               wxPoint pt(sizeStamp.x * (prevTool & 0x03), sizeStamp.y * (prevTool >> 2));\r
-               dc.Blit(pt.x, pt.y, sizeStamp.x, sizeStamp.y, &memDC, pt.x, pt.y, wxSRC_INVERT);\r
-       }\r
-\r
-       memDC.SelectObject(wxNullBitmap);\r
-}\r
-\r
-//\r
-// Find which tool we're pointing at\r
-//\r
-ToolType ToolWindow::FindSelectedTool(void)\r
-{\r
-       // Get mouse coords relative to the tool palette window\r
-       wxPoint pt = ScreenToClient(wxGetMousePosition());\r
-\r
-       // Divide mouse coords by the bitmap stamp size to find which one is pointed to\r
-       uint32 x = (uint32)pt.x / sizeStamp.x, y = (uint32)pt.y / sizeStamp.y;\r
-\r
-       // Preset failure into newTool, in case no new tool is selected\r
-       ToolType newTool = TOOLNone;\r
-\r
-       // NOTE: This works because x and y are UNSIGNED\r
-       if (x < 4 && y < 2)\r
-               newTool = (ToolType)((y * 4) + x);\r
-\r
-       return newTool;\r
-}\r
+//
+// TOOLWINDOW.CPP - Tool Palette window
+// by James L. Hammons
+// (C) 2008 Underground Software
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  08/28/2008  Created this file
+//
+
+// FIXED:
+//
+// STILL TO BE DONE:
+//
+//
+
+// Uncomment this for debugging...
+#define DEBUG
+#define DEBUGFOO            // Various tool debugging...
+#define DEBUGTP                                // Toolpalette debugging...
+
+#include "toolwindow.h"
+#include "types.h"
+
+// Pixmap resources
+
+#include "res/toolpal1.xpm"                                            // Docs say this is portable... Let's see!
+
+
+BEGIN_EVENT_TABLE(ToolWindow, wxFrame)
+       EVT_PAINT(ToolWindow::OnPaint)
+END_EVENT_TABLE()
+
+
+ToolWindow::ToolWindow(wxFrame * parent, const wxString &title, const wxPoint &pos,
+       const wxSize &size, long style): wxFrame(parent, -1, title, pos, size, style),
+       bmp(NULL), prevTool(TOOLNone)
+{
+       bmp = new wxBitmap(toolpal1_xpm);
+
+       // Set up sizes
+
+       sizeTPBM.x = bmp->GetWidth(), sizeTPBM.y = bmp->GetHeight();
+       sizeStamp.x = sizeTPBM.x / 4, sizeStamp.y = sizeTPBM.y / 2;
+
+       SetSize(0, 0, sizeTPBM.x, sizeTPBM.y);
+       Show(false);
+}
+
+ToolWindow::~ToolWindow()
+{
+       if (bmp)
+               delete bmp;
+}
+
+void ToolWindow::OnPaint(wxPaintEvent &e)
+{
+       wxPaintDC dc(this);
+
+       wxMemoryDC memDC;
+       memDC.SelectObject(*bmp);
+       dc.Blit(0, 0, sizeTPBM.x, sizeTPBM.y, &memDC, 0, 0, wxCOPY);
+
+       if (prevTool != -1)
+       {
+           //need ul corner of bitmap, ul corner of dest, width/height
+               wxPoint pt(sizeStamp.x * (prevTool & 0x03), sizeStamp.y * (prevTool >> 2));
+               dc.Blit(pt.x, pt.y, sizeStamp.x, sizeStamp.y, &memDC, pt.x, pt.y, wxSRC_INVERT);
+       }
+
+       memDC.SelectObject(wxNullBitmap);
+}
+
+//
+// Find which tool we're pointing at
+//
+ToolType ToolWindow::FindSelectedTool(void)
+{
+       // Get mouse coords relative to the tool palette window
+       wxPoint pt = ScreenToClient(wxGetMousePosition());
+
+       // Divide mouse coords by the bitmap stamp size to find which one is pointed to
+       uint32 x = (uint32)pt.x / sizeStamp.x, y = (uint32)pt.y / sizeStamp.y;
+
+       // Preset failure into newTool, in case no new tool is selected
+       ToolType newTool = TOOLNone;
+
+       // NOTE: This works because x and y are UNSIGNED
+       if (x < 4 && y < 2)
+               newTool = (ToolType)((y * 4) + x);
+
+       return newTool;
+}
index 5d1ee3ee74eac42bc3ed8e48d38c8bae89f880df..d4eab9f0371fd400ef9a40e91b3d50663348057b 100755 (executable)
@@ -1,47 +1,47 @@
-//\r
-// TOOLWINDOW.H: Header file\r
-//\r
-// by James L. Hammons\r
-// (C) 2008 Underground Software\r
-//\r
-\r
-#ifndef __TOOLWINDOW_H__\r
-#define __TOOLWINDOW_H__\r
-\r
-#include <wx/wx.h>                                                             // So that whoever uses this can without having\r
-                                                                                               // to pull in a bunch of references manually\r
-\r
-// Enumerations (prolly go into ToolWindow class--?)\r
-\r
-enum ToolType {\r
-       TOOLNone = -1,                                                  // No tool\r
-       TOOLSelect = 0,                                                 // The "selection" tool\r
-       TOOLPolySelect,                                                 // Polygon selection tool\r
-       TOOLScroll,                                                             // Scroll window tool\r
-       TOOLZoom,                                                               // Zoom window tool\r
-       TOOLAddPt,                                                              // Add point tool\r
-       TOOLAddPoly,                                                    // Polygon creation tool\r
-       TOOLDelPt,                                                              // Delete point tool\r
-       TOOLDelPoly                                                             // Delete polygon tool\r
-};\r
-\r
-class ToolWindow: public wxFrame\r
-{\r
-       private:\r
-       protected:\r
-       public:\r
-               wxBitmap * bmp;\r
-               wxPoint sizeStamp, sizeTPBM;\r
-               ToolType prevTool;\r
-\r
-               // Constructor and destructor\r
-               ToolWindow(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style);\r
-               ~ToolWindow(void);\r
-\r
-               void OnPaint(wxPaintEvent &e);\r
-               ToolType FindSelectedTool(void);\r
-\r
-       DECLARE_EVENT_TABLE()\r
-};\r
-\r
-#endif // __TOOLWINDOW_H__\r
+//
+// TOOLWINDOW.H: Header file
+//
+// by James L. Hammons
+// (C) 2008 Underground Software
+//
+
+#ifndef __TOOLWINDOW_H__
+#define __TOOLWINDOW_H__
+
+#include <wx/wx.h>                                                             // So that whoever uses this can without having
+                                                                                               // to pull in a bunch of references manually
+
+// Enumerations (prolly go into ToolWindow class--?)
+
+enum ToolType {
+       TOOLNone = -1,                                                  // No tool
+       TOOLSelect = 0,                                                 // The "selection" tool
+       TOOLPolySelect,                                                 // Polygon selection tool
+       TOOLScroll,                                                             // Scroll window tool
+       TOOLZoom,                                                               // Zoom window tool
+       TOOLAddPt,                                                              // Add point tool
+       TOOLAddPoly,                                                    // Polygon creation tool
+       TOOLDelPt,                                                              // Delete point tool
+       TOOLDelPoly                                                             // Delete polygon tool
+};
+
+class ToolWindow: public wxFrame
+{
+       private:
+       protected:
+       public:
+               wxBitmap * bmp;
+               wxPoint sizeStamp, sizeTPBM;
+               ToolType prevTool;
+
+               // Constructor and destructor
+               ToolWindow(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style);
+               ~ToolWindow(void);
+
+               void OnPaint(wxPaintEvent &e);
+               ToolType FindSelectedTool(void);
+
+       DECLARE_EVENT_TABLE()
+};
+
+#endif // __TOOLWINDOW_H__
index 3bf6dbaebb73455f3359dce9fd8eb91e58af7963..9efa64111ead88df79a55d262ccf26d835e81750 100755 (executable)
@@ -1,46 +1,46 @@
-//\r
-// Resource includes\r
-//\r
-// by James L. Hammons\r
-//\r
-\r
-// Uncomment this to debug logging...\r
-//Actually, this is done on a file by file basis and NOT here...\r
-//#define DEBUG\r
-\r
-//\r
-// Common equates also used in the resource file\r
-//\r
-\r
-#define        IDI_ICON                        0x01L           // IDs same as in ttedit.asm\r
-#define        IDM_MENU                        0x02L\r
-#define        IDA_ACCEL                       0x03L\r
-#define        IDD_ABOUT                       0x04L\r
-#define IDR_TOOLBAR1           0x05L\r
-#define IDB_TOOLBAR1           0x06L\r
-#define IDB_TOOLPAL1           0x07L\r
-#define IDC_CURSOR1                    0x08L\r
-#define IDC_CURSOR2                    0x09L\r
-#define IDC_CURSOR3                    0x0AL\r
-#define IDC_CURSOR4                    0x0BL\r
-#define IDC_CURSOR5                    0x0CL\r
-#define IDC_CURSOR6                    0x0DL\r
-#define IDC_CURSOR7                    0x0EL\r
-#define IDC_CURSOR8                    0x0FL\r
-\r
-#define        IDS_SYSMENU                     0x010L\r
-#define        IDM_FILEMENU            0x011L\r
-#define        IDM_HELPMENU            0x012L\r
-\r
-#define        IDM_NEW                         0x020L\r
-#define        IDM_OPEN                        0x021L\r
-#define        IDM_SAVE                        0x022L\r
-#define        IDM_SAVEAS                      0x023L\r
-#define        IDM_EXIT                        0x024L\r
-#define        IDM_HELPTOPICS          0x025L\r
-#define        IDM_ABOUT                       0x026L\r
-\r
-#define        ID_TBLEFT                       0x030L\r
-#define        ID_TBRIGHT                      0x031L\r
-#define        ID_TBCHARWIN            0x032L\r
-\r
+//
+// Resource includes
+//
+// by James L. Hammons
+//
+
+// Uncomment this to debug logging...
+//Actually, this is done on a file by file basis and NOT here...
+//#define DEBUG
+
+//
+// Common equates also used in the resource file
+//
+
+#define        IDI_ICON                        0x01L           // IDs same as in ttedit.asm
+#define        IDM_MENU                        0x02L
+#define        IDA_ACCEL                       0x03L
+#define        IDD_ABOUT                       0x04L
+#define IDR_TOOLBAR1           0x05L
+#define IDB_TOOLBAR1           0x06L
+#define IDB_TOOLPAL1           0x07L
+#define IDC_CURSOR1                    0x08L
+#define IDC_CURSOR2                    0x09L
+#define IDC_CURSOR3                    0x0AL
+#define IDC_CURSOR4                    0x0BL
+#define IDC_CURSOR5                    0x0CL
+#define IDC_CURSOR6                    0x0DL
+#define IDC_CURSOR7                    0x0EL
+#define IDC_CURSOR8                    0x0FL
+
+#define        IDS_SYSMENU                     0x010L
+#define        IDM_FILEMENU            0x011L
+#define        IDM_HELPMENU            0x012L
+
+#define        IDM_NEW                         0x020L
+#define        IDM_OPEN                        0x021L
+#define        IDM_SAVE                        0x022L
+#define        IDM_SAVEAS                      0x023L
+#define        IDM_EXIT                        0x024L
+#define        IDM_HELPTOPICS          0x025L
+#define        IDM_ABOUT                       0x026L
+
+#define        ID_TBLEFT                       0x030L
+#define        ID_TBRIGHT                      0x031L
+#define        ID_TBCHARWIN            0x032L
+
index 3c31541a8934d42c68804eac35c8e504ddb97afd..116bd4abfcea9b1daa9dd7dfb0446e3ad3546bdc 100755 (executable)
-//\r
-// TTEDIT.CPP - The TrueType Editor\r
-// by James L. Hammons\r
-// (C) 2004 Underground Software\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  -------------------------------------------------------------\r
-// JLH  04/10/2002  Created this file\r
-// JLH  05/10/2004  Translated file from ASM to CPP\r
-// JLH  05/14/2004  Added rudimentary editing capability to tool palette tools\r
-// JLH  11/18/2006  Initial port to Linux\r
-// JLH  08/27/2008  Fixed tool palette focus problems\r
-// JLH  08/28/2008  Split out classes defined here into separate files\r
-//\r
-\r
-// FIXED:\r
-//\r
-// - Fix problem with tool palette not getting focus 1st time it's called up [DONE]\r
-// - Split out windows/classes defined here into their own files [DONE]\r
-//\r
-// STILL TO BE DONE:\r
-//\r
-// - Fix bug in Glyphpoints when dragging on an empty canvas or loading a font\r
-// - Fix scrolling, zooming, settings (ini)\r
-// - Finish conversion to wxWidgets for cross-platform portability\r
-// - Fix problem with owned window causing main window refresh problems\r
-//   (ironically enough, it doesn't seem to be a problem anymore...)\r
-//\r
-\r
-// Uncomment this for debugging...\r
-#define DEBUG\r
-#define DEBUGFOO                       // Various tool debugging...\r
-#define DEBUGTP                                // Toolpalette debugging...\r
-\r
-#include "ttedit.h"\r
-#include "charwindow.h"\r
-#include "toolwindow.h"\r
-#include "editwindow.h"\r
-#include "tte_res.h"                                                   // Resource IDs\r
-#ifdef DEBUG\r
-#include "debug.h"\r
-#endif\r
-\r
-// Pixmap resouces\r
-\r
-#include "res/cur1.xpm"\r
-#include "res/cur2.xpm"\r
-#include "res/cur3.xpm"\r
-#include "res/cur4.xpm"\r
-#include "res/cur5.xpm"\r
-#include "res/cur6.xpm"\r
-#include "res/cur7.xpm"\r
-#include "res/cur8.xpm"\r
-#include "res/ttedit.xpm"                                              // *nix only, but small enough to not matter\r
-#include "res/tool1.xpm"\r
-#include "res/tool2.xpm"\r
-#include "res/tool3.xpm"\r
-\r
-\r
-IMPLEMENT_APP(TTEditApp)                                               // Run the main application loop\r
-\r
-bool TTEditApp::OnInit()\r
-{\r
-       wxLog * logTarget = new wxLogStderr();//fopen("!ttedit_log.txt", "wb"));\r
-       wxLog::SetActiveTarget(logTarget);\r
-#ifdef DEBUG\r
-       OpenDebugLog();\r
-#endif\r
-\r
-       // Initialize all the top-level window members to NULL.\r
-       mainFrame = NULL;\r
-       charWin = NULL;\r
-       toolPalette = NULL;\r
-\r
-//Shouldn't we check to see if it was successful? This just assumes\r
-       CreateResources();\r
-\r
-       mainFrame = new TTEditFrame(NULL, _("TTEdit"), wxPoint(155, 165), wxSize(300, 300),\r
-               wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE);\r
-//             wxMINIMIZE_BOX | wxRESIZE_BOX | wxMAXIMIZE_BOX | | wxSYSTEM_MENU | wxCAPTION);\r
-\r
-//     charWin = new CharWindow(NULL);//, _T("Own3d W1nd0w"), wxDefaultPosition, wxDefaultSize);\r
-       charWin = new CharWindow(mainFrame, _("Own3d W1nd0w"), wxDefaultPosition, wxDefaultSize,\r
-               wxCAPTION | wxRESIZE_BORDER);\r
-\r
-       toolPalette = new ToolWindow(mainFrame, _(""), wxDefaultPosition, wxDefaultSize,\r
-               wxBORDER_NONE | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT);\r
-\r
-       return true;\r
-}\r
-\r
-int TTEditApp::OnExit()\r
-{\r
-#ifdef DEBUG\r
-       CloseDebugLog();\r
-#endif\r
-\r
-       return 0;\r
-}\r
-\r
-void TTEditApp::CreateResources(void)\r
-{\r
-       // This is a sucky way to create cursors, but at least it's cross-platform...\r
-       // NOTE: Need to fix hotspots on a few... !!! FIX !!!\r
-\r
-       wxBitmap cursorBM1(cur1_xpm);\r
-       wxImage cursorImage1 = cursorBM1.ConvertToImage();\r
-       cursorImage1.SetMaskFromImage(cursorImage1, 0xFF, 0xFF, 0xFF);\r
-       cur[0] = new wxCursor(cursorImage1);\r
-\r
-       wxBitmap cursorBM2(cur2_xpm);\r
-       wxImage cursorImage2 = cursorBM2.ConvertToImage();\r
-       cursorImage2.SetMaskFromImage(cursorImage2, 0xFF, 0xFF, 0xFF);\r
-       cur[1] = new wxCursor(cursorImage2);\r
-\r
-       wxBitmap cursorBM3(cur3_xpm);\r
-       wxImage cursorImage3 = cursorBM3.ConvertToImage();\r
-       cursorImage3.SetMaskFromImage(cursorImage3, 0xFF, 0xFF, 0xFF);\r
-       cur[2] = new wxCursor(cursorImage3);\r
-\r
-       wxBitmap cursorBM4(cur4_xpm);\r
-       wxImage cursorImage4 = cursorBM4.ConvertToImage();\r
-       cursorImage4.SetMaskFromImage(cursorImage4, 0xFF, 0xFF, 0xFF);\r
-       cur[3] = new wxCursor(cursorImage4);\r
-\r
-       wxBitmap cursorBM5(cur5_xpm);\r
-       wxImage cursorImage5 = cursorBM5.ConvertToImage();\r
-       cursorImage5.SetMaskFromImage(cursorImage5, 0xFF, 0xFF, 0xFF);\r
-       cur[4] = new wxCursor(cursorImage5);\r
-\r
-       wxBitmap cursorBM6(cur6_xpm);\r
-       wxImage cursorImage6 = cursorBM6.ConvertToImage();\r
-       cursorImage6.SetMaskFromImage(cursorImage6, 0xFF, 0xFF, 0xFF);\r
-       cur[5] = new wxCursor(cursorImage6);\r
-\r
-       wxBitmap cursorBM7(cur7_xpm);\r
-       wxImage cursorImage7 = cursorBM7.ConvertToImage();\r
-       cursorImage7.SetMaskFromImage(cursorImage7, 0xFF, 0xFF, 0xFF);\r
-       cur[6] = new wxCursor(cursorImage7);\r
-\r
-       wxBitmap cursorBM8(cur8_xpm);\r
-       wxImage cursorImage8 = cursorBM8.ConvertToImage();\r
-       cursorImage8.SetMaskFromImage(cursorImage8, 0xFF, 0xFF, 0xFF);\r
-       cur[7] = new wxCursor(cursorImage8);\r
-}\r
-\r
-\r
-BEGIN_EVENT_TABLE(TTEditFrame, wxFrame)\r
-       EVT_MENU(IDM_OPEN, TTEditFrame::OnOpen)\r
-       EVT_MENU(IDM_EXIT, TTEditFrame::OnExit)\r
-       EVT_MENU(IDM_ABOUT, TTEditFrame::OnAbout)\r
-       EVT_CLOSE(TTEditFrame::OnCloseWindow)\r
-END_EVENT_TABLE()\r
-\r
-TTEditFrame::TTEditFrame(wxFrame * parent, const wxString &title, const wxPoint &pos,\r
-       const wxSize &size, long style): wxFrame(parent, -1, title, pos, size, style), app(wxGetApp()), mainWindow(NULL)\r
-{\r
-       // Initialize child subwindow members (and hopefully avoid subtle bugs)\r
-//     mainWindow = NULL;\r
-\r
-       SetIcon(wxICON(ttedit));\r
-//     CreateStatusBar(2);                                                     // Create 2 panes\r
-       int widths[2] = { -1, 120 };\r
-       wxStatusBar * sb = CreateStatusBar(2, 0);       // Create 2 panes\r
-       sb->SetStatusWidths(2, widths);\r
-       wxToolBar * tb = CreateToolBar();\r
-\r
-       if (tb != NULL)\r
-       {\r
-               // Create buttons\r
-\r
-               wxBitmap tool1(tool1_xpm);\r
-               wxBitmap tool2(tool2_xpm);\r
-               wxBitmap tool3(tool3_xpm);\r
-\r
-               tb->AddTool(ID_TBLEFT, _("Prev char"), tool1, _("Go to prev char"), wxITEM_NORMAL);\r
-               tb->AddTool(ID_TBRIGHT, _("Next char"), tool2, _("Go to next char"), wxITEM_NORMAL);\r
-               tb->AddTool(ID_TBCHARWIN, _("Char Wnd"), tool3, _("Toggle char window"), wxITEM_NORMAL);\r
-               tb->Realize();\r
-       }\r
-\r
-       // Create a menu bar for the frame\r
-       menuBar = new wxMenuBar;\r
-       wxMenu * menu1 = new wxMenu;\r
-       menu1->Append(IDM_NEW, _("&New\tCtrl+N"), _("Create a new font."));\r
-       menu1->Append(IDM_OPEN, _("&Open...\tCtrl+O"), _("Opens an existing font."));\r
-       menu1->Append(IDM_SAVE, _("&Save\tCtrl+S"), _("Save the current font."));\r
-       menu1->Append(IDM_SAVEAS, _("Save &As..."), _("Save the current font under a different name."));\r
-       menu1->AppendSeparator();\r
-       menu1->Append(IDM_EXIT, _("E&xit\tAlt+X"), _("Quits the TTEdit program."));\r
-       menuBar->Append(menu1, _("&File"));\r
-       wxMenu * menu2 = new wxMenu;\r
-       menu2->Append(IDM_HELPTOPICS, _("&Help Topics"), _("Displays the Help contents and index."));\r
-       menu2->AppendSeparator();\r
-       menu2->Append(IDM_ABOUT, _("&About TTEdit"), _("Displays information about TTEdit."));\r
-       menuBar->Append(menu2, _("&Help"));\r
-       SetMenuBar(menuBar);\r
-\r
-       // Create child subwindows\r
-       mainWindow = new TTEditWindow(this);\r
-\r
-       Centre(wxBOTH);                                                         // Centre frame on the screen\r
-       Show(true);                                                                     // Show the frame\r
-}\r
-\r
-TTEditFrame::~TTEditFrame()\r
-{\r
-}\r
-\r
-void TTEditFrame::OnOpen(wxCommandEvent &e)\r
-{\r
-       wxFileDialog fd(this, _("Choose a font to load"), _(""), _(""), _("TTF files (*.ttf)|*.ttf|All files (*.*)|*.*"), wxOPEN);\r
-\r
-       if (fd.ShowModal() != wxID_OK)\r
-           return;\r
-\r
-// Hmm. The font object is causing a massive crash... (gdb says it's in "Load")\r
-       if (app.font.Load((char *)fd.GetPath().c_str()) != true)\r
-       {\r
-               wxMessageDialog dlg(NULL, _("Load font failed!"), _("Houston, we have a problem..."), wxOK | wxICON_ERROR);\r
-               dlg.ShowModal();\r
-       }\r
-\r
-//Huzzah! It works! Now just need scaling, scrolling, etc...\r
-//     pts = app.font.GetGlyphPoints(45);\r
-}\r
-\r
-void TTEditFrame::OnAbout(wxCommandEvent &e)\r
-{\r
-       wxMessageDialog dlg(NULL, _("TrueType Edit v1.0.1\n\nA handy tool for editing TrueType fonts!\nby James \"Shamus\" Hammons\n(C) 2006 Underground Software"), _("About TrueType Edit"), wxOK | wxICON_INFORMATION);\r
-       dlg.ShowModal();\r
-}\r
-\r
-void TTEditFrame::OnExit(wxCommandEvent &e)\r
-{\r
-       app.toolPalette->Destroy();\r
-       this->Destroy();\r
-}\r
-\r
-void TTEditFrame::OnCloseWindow(wxCloseEvent &e)\r
-{\r
-       app.toolPalette->Destroy();\r
-       this->Destroy();\r
-}\r
+//
+// TTEDIT.CPP - The TrueType Editor
+// by James L. Hammons
+// (C) 2004 Underground Software
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  04/10/2002  Created this file
+// JLH  05/10/2004  Translated file from ASM to CPP
+// JLH  05/14/2004  Added rudimentary editing capability to tool palette tools
+// JLH  11/18/2006  Initial port to Linux
+// JLH  08/27/2008  Fixed tool palette focus problems
+// JLH  08/28/2008  Split out classes defined here into separate files
+//
+
+// FIXED:
+//
+// - Fix problem with tool palette not getting focus 1st time it's called up [DONE]
+// - Split out windows/classes defined here into their own files [DONE]
+//
+// STILL TO BE DONE:
+//
+// - Fix bug in Glyphpoints when dragging on an empty canvas or loading a font
+// - Fix scrolling, zooming, settings (ini)
+// - Finish conversion to wxWidgets for cross-platform portability
+// - Fix problem with owned window causing main window refresh problems
+//   (ironically enough, it doesn't seem to be a problem anymore...)
+//
+
+// Uncomment this for debugging...
+#define DEBUG
+#define DEBUGFOO                       // Various tool debugging...
+#define DEBUGTP                                // Toolpalette debugging...
+
+#include "ttedit.h"
+#include "charwindow.h"
+#include "toolwindow.h"
+#include "editwindow.h"
+#include "tte_res.h"                                                   // Resource IDs
+#ifdef DEBUG
+#include "debug.h"
+#endif
+
+// Pixmap resouces
+
+#include "res/cur1.xpm"
+#include "res/cur2.xpm"
+#include "res/cur3.xpm"
+#include "res/cur4.xpm"
+#include "res/cur5.xpm"
+#include "res/cur6.xpm"
+#include "res/cur7.xpm"
+#include "res/cur8.xpm"
+#include "res/ttedit.xpm"                                              // *nix only, but small enough to not matter
+#include "res/tool1.xpm"
+#include "res/tool2.xpm"
+#include "res/tool3.xpm"
+
+
+IMPLEMENT_APP(TTEditApp)                                               // Run the main application loop
+
+bool TTEditApp::OnInit()
+{
+       wxLog * logTarget = new wxLogStderr();//fopen("!ttedit_log.txt", "wb"));
+       wxLog::SetActiveTarget(logTarget);
+#ifdef DEBUG
+       OpenDebugLog();
+#endif
+
+       // Initialize all the top-level window members to NULL.
+       mainFrame = NULL;
+       charWin = NULL;
+       toolPalette = NULL;
+
+//Shouldn't we check to see if it was successful? This just assumes
+       CreateResources();
+
+       mainFrame = new TTEditFrame(NULL, _("TTEdit"), wxPoint(155, 165), wxSize(300, 300),
+               wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE);
+//             wxMINIMIZE_BOX | wxRESIZE_BOX | wxMAXIMIZE_BOX | | wxSYSTEM_MENU | wxCAPTION);
+
+//     charWin = new CharWindow(NULL);//, _T("Own3d W1nd0w"), wxDefaultPosition, wxDefaultSize);
+       charWin = new CharWindow(mainFrame, _("Own3d W1nd0w"), wxDefaultPosition, wxDefaultSize,
+               wxCAPTION | wxRESIZE_BORDER);
+
+       toolPalette = new ToolWindow(mainFrame, _(""), wxDefaultPosition, wxDefaultSize,
+               wxBORDER_NONE | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT);
+
+       return true;
+}
+
+int TTEditApp::OnExit()
+{
+#ifdef DEBUG
+       CloseDebugLog();
+#endif
+
+       return 0;
+}
+
+void TTEditApp::CreateResources(void)
+{
+       // This is a sucky way to create cursors, but at least it's cross-platform...
+       // NOTE: Need to fix hotspots on a few... !!! FIX !!!
+
+       wxBitmap cursorBM1(cur1_xpm);
+       wxImage cursorImage1 = cursorBM1.ConvertToImage();
+       cursorImage1.SetMaskFromImage(cursorImage1, 0xFF, 0xFF, 0xFF);
+       cur[0] = new wxCursor(cursorImage1);
+
+       wxBitmap cursorBM2(cur2_xpm);
+       wxImage cursorImage2 = cursorBM2.ConvertToImage();
+       cursorImage2.SetMaskFromImage(cursorImage2, 0xFF, 0xFF, 0xFF);
+       cur[1] = new wxCursor(cursorImage2);
+
+       wxBitmap cursorBM3(cur3_xpm);
+       wxImage cursorImage3 = cursorBM3.ConvertToImage();
+       cursorImage3.SetMaskFromImage(cursorImage3, 0xFF, 0xFF, 0xFF);
+       cur[2] = new wxCursor(cursorImage3);
+
+       wxBitmap cursorBM4(cur4_xpm);
+       wxImage cursorImage4 = cursorBM4.ConvertToImage();
+       cursorImage4.SetMaskFromImage(cursorImage4, 0xFF, 0xFF, 0xFF);
+       cur[3] = new wxCursor(cursorImage4);
+
+       wxBitmap cursorBM5(cur5_xpm);
+       wxImage cursorImage5 = cursorBM5.ConvertToImage();
+       cursorImage5.SetMaskFromImage(cursorImage5, 0xFF, 0xFF, 0xFF);
+       cur[4] = new wxCursor(cursorImage5);
+
+       wxBitmap cursorBM6(cur6_xpm);
+       wxImage cursorImage6 = cursorBM6.ConvertToImage();
+       cursorImage6.SetMaskFromImage(cursorImage6, 0xFF, 0xFF, 0xFF);
+       cur[5] = new wxCursor(cursorImage6);
+
+       wxBitmap cursorBM7(cur7_xpm);
+       wxImage cursorImage7 = cursorBM7.ConvertToImage();
+       cursorImage7.SetMaskFromImage(cursorImage7, 0xFF, 0xFF, 0xFF);
+       cur[6] = new wxCursor(cursorImage7);
+
+       wxBitmap cursorBM8(cur8_xpm);
+       wxImage cursorImage8 = cursorBM8.ConvertToImage();
+       cursorImage8.SetMaskFromImage(cursorImage8, 0xFF, 0xFF, 0xFF);
+       cur[7] = new wxCursor(cursorImage8);
+}
+
+
+BEGIN_EVENT_TABLE(TTEditFrame, wxFrame)
+       EVT_MENU(IDM_OPEN, TTEditFrame::OnOpen)
+       EVT_MENU(IDM_EXIT, TTEditFrame::OnExit)
+       EVT_MENU(IDM_ABOUT, TTEditFrame::OnAbout)
+       EVT_CLOSE(TTEditFrame::OnCloseWindow)
+END_EVENT_TABLE()
+
+TTEditFrame::TTEditFrame(wxFrame * parent, const wxString &title, const wxPoint &pos,
+       const wxSize &size, long style): wxFrame(parent, -1, title, pos, size, style), app(wxGetApp()), mainWindow(NULL)
+{
+       // Initialize child subwindow members (and hopefully avoid subtle bugs)
+//     mainWindow = NULL;
+
+       SetIcon(wxICON(ttedit));
+//     CreateStatusBar(2);                                                     // Create 2 panes
+       int widths[2] = { -1, 120 };
+       wxStatusBar * sb = CreateStatusBar(2, 0);       // Create 2 panes
+       sb->SetStatusWidths(2, widths);
+       wxToolBar * tb = CreateToolBar();
+
+       if (tb != NULL)
+       {
+               // Create buttons
+
+               wxBitmap tool1(tool1_xpm);
+               wxBitmap tool2(tool2_xpm);
+               wxBitmap tool3(tool3_xpm);
+
+               tb->AddTool(ID_TBLEFT, _("Prev char"), tool1, _("Go to prev char"), wxITEM_NORMAL);
+               tb->AddTool(ID_TBRIGHT, _("Next char"), tool2, _("Go to next char"), wxITEM_NORMAL);
+               tb->AddTool(ID_TBCHARWIN, _("Char Wnd"), tool3, _("Toggle char window"), wxITEM_NORMAL);
+               tb->Realize();
+       }
+
+       // Create a menu bar for the frame
+       menuBar = new wxMenuBar;
+       wxMenu * menu1 = new wxMenu;
+       menu1->Append(IDM_NEW, _("&New\tCtrl+N"), _("Create a new font."));
+       menu1->Append(IDM_OPEN, _("&Open...\tCtrl+O"), _("Opens an existing font."));
+       menu1->Append(IDM_SAVE, _("&Save\tCtrl+S"), _("Save the current font."));
+       menu1->Append(IDM_SAVEAS, _("Save &As..."), _("Save the current font under a different name."));
+       menu1->AppendSeparator();
+       menu1->Append(IDM_EXIT, _("E&xit\tAlt+X"), _("Quits the TTEdit program."));
+       menuBar->Append(menu1, _("&File"));
+       wxMenu * menu2 = new wxMenu;
+       menu2->Append(IDM_HELPTOPICS, _("&Help Topics"), _("Displays the Help contents and index."));
+       menu2->AppendSeparator();
+       menu2->Append(IDM_ABOUT, _("&About TTEdit"), _("Displays information about TTEdit."));
+       menuBar->Append(menu2, _("&Help"));
+       SetMenuBar(menuBar);
+
+       // Create child subwindows
+       mainWindow = new TTEditWindow(this);
+
+       Centre(wxBOTH);                                                         // Centre frame on the screen
+       Show(true);                                                                     // Show the frame
+}
+
+TTEditFrame::~TTEditFrame()
+{
+}
+
+void TTEditFrame::OnOpen(wxCommandEvent &e)
+{
+       wxFileDialog fd(this, _("Choose a font to load"), _(""), _(""), _("TTF files (*.ttf)|*.ttf|All files (*.*)|*.*"), wxOPEN);
+
+       if (fd.ShowModal() != wxID_OK)
+           return;
+
+// Hmm. The font object is causing a massive crash... (gdb says it's in "Load")
+       if (app.font.Load((char *)fd.GetPath().c_str()) != true)
+       {
+               wxMessageDialog dlg(NULL, _("Load font failed!"), _("Houston, we have a problem..."), wxOK | wxICON_ERROR);
+               dlg.ShowModal();
+       }
+
+//Huzzah! It works! Now just need scaling, scrolling, etc...
+//     pts = app.font.GetGlyphPoints(45);
+}
+
+void TTEditFrame::OnAbout(wxCommandEvent &e)
+{
+       wxMessageDialog dlg(NULL, _("TrueType Edit v1.0.1\n\nA handy tool for editing TrueType fonts!\nby James \"Shamus\" Hammons\n(C) 2006 Underground Software"), _("About TrueType Edit"), wxOK | wxICON_INFORMATION);
+       dlg.ShowModal();
+}
+
+void TTEditFrame::OnExit(wxCommandEvent &e)
+{
+       app.toolPalette->Destroy();
+       this->Destroy();
+}
+
+void TTEditFrame::OnCloseWindow(wxCloseEvent &e)
+{
+       app.toolPalette->Destroy();
+       this->Destroy();
+}
index 7f1eba7da80992e2e1d76a1da95bde172d3cdce5..6545455efe0304639ee9575664c8c4be2f3e711e 100755 (executable)
@@ -1,63 +1,63 @@
-//\r
-// TTEDIT.H: Header file\r
-//\r
-// by James L. Hammons\r
-// (C) 2008 Underground Software\r
-//\r
-\r
-#ifndef __TTEDIT_H__\r
-#define __TTEDIT_H__\r
-\r
-#include <wx/wx.h>                                                             // So that whoever uses this can without having\r
-                                                                                               // to pull in a bunch of references manually\r
-#include "ttf.h"\r
-\r
-// Forward declarations\r
-\r
-class TTEditFrame;\r
-class TTEditWindow;\r
-class CharWindow;\r
-class ToolWindow;\r
-\r
-//\r
-// Class representing the entire Application\r
-//\r
-class TTEditApp: public wxApp\r
-{\r
-       public:\r
-               TTEditFrame * mainFrame;\r
-               CharWindow * charWin;\r
-               ToolWindow * toolPalette;\r
-               TTF font;\r
-               wxCursor * cur[8];\r
-\r
-               bool OnInit();\r
-               int OnExit();\r
-               void CreateResources(void);\r
-};\r
-\r
-DECLARE_APP(TTEditApp)\r
-\r
-class TTEditFrame: public wxFrame\r
-{\r
-       private:\r
-       protected:\r
-       public:\r
-               TTEditApp & app;                                                // Reference to the application object\r
-               // Subwindows for reference within the program.\r
-               TTEditWindow * mainWindow;\r
-               wxMenuBar * menuBar;\r
-\r
-               // Constructor and destructor\r
-               TTEditFrame(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style);\r
-               ~TTEditFrame(void);\r
-\r
-               void OnCloseWindow(wxCloseEvent &e);\r
-               void OnOpen(wxCommandEvent &e);\r
-               void OnExit(wxCommandEvent &e);\r
-               void OnAbout(wxCommandEvent &e);\r
-\r
-       DECLARE_EVENT_TABLE()\r
-};\r
-\r
-#endif // __TTEDIT_H__\r
+//
+// TTEDIT.H: Header file
+//
+// by James L. Hammons
+// (C) 2008 Underground Software
+//
+
+#ifndef __TTEDIT_H__
+#define __TTEDIT_H__
+
+#include <wx/wx.h>                                                             // So that whoever uses this can without having
+                                                                                               // to pull in a bunch of references manually
+#include "ttf.h"
+
+// Forward declarations
+
+class TTEditFrame;
+class TTEditWindow;
+class CharWindow;
+class ToolWindow;
+
+//
+// Class representing the entire Application
+//
+class TTEditApp: public wxApp
+{
+       public:
+               TTEditFrame * mainFrame;
+               CharWindow * charWin;
+               ToolWindow * toolPalette;
+               TTF font;
+               wxCursor * cur[8];
+
+               bool OnInit();
+               int OnExit();
+               void CreateResources(void);
+};
+
+DECLARE_APP(TTEditApp)
+
+class TTEditFrame: public wxFrame
+{
+       private:
+       protected:
+       public:
+               TTEditApp & app;                                                // Reference to the application object
+               // Subwindows for reference within the program.
+               TTEditWindow * mainWindow;
+               wxMenuBar * menuBar;
+
+               // Constructor and destructor
+               TTEditFrame(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style);
+               ~TTEditFrame(void);
+
+               void OnCloseWindow(wxCloseEvent &e);
+               void OnOpen(wxCommandEvent &e);
+               void OnExit(wxCommandEvent &e);
+               void OnAbout(wxCommandEvent &e);
+
+       DECLARE_EVENT_TABLE()
+};
+
+#endif // __TTEDIT_H__
index 124468728d8efcdf58d8e94c516484faaf95f3bd..ce312a8d6dfc2ddd70265dfc0f9265f4a13028ae 100755 (executable)
-//\r
-// TTF.CPP - The TrueType class\r
-// by James L. Hammons\r
-// (C) 2005 Underground Software\r
-//\r
-// This class encapsulates all the complexity of a TrueType Font File\r
-// database.  Included are functions to load, save, & initialize the\r
-// TTF database, move, add, & delete points & glyphs, i.e. manipulate\r
-// a TTF file in just about any way imaginable!\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  -------------------------------------------------------------\r
-// JLH  ??/??/199?  Created this file\r
-//\r
-//\r
-// STILL TO BE DONE:\r
-//\r
-// - Eliminate ALL references to BYTE, WORD, SBYTE, SWORD, etc.\r
-//\r
-\r
-#include <stdio.h>                                                             // For file handling, etc.                                                                                              //\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include "charnames.h"\r
-#include "ttf.h"\r
-\r
-#define TTFDEBUG\r
-\r
-#ifdef TTFDEBUG\r
-#include "debug.h"\r
-#endif\r
-\r
-#define NUMTABS  24                   // Number of distinct tables\r
-\r
-\r
-/*void fskip(HANDLE file, uint32 bytesToSkip)\r
-{\r
-       SetFilePointer(file, (LONG)bytesToSkip, NULL, FILE_CURRENT);\r
-}*/\r
-\r
-//\r
-// Get a BYTE from the current file...\r
-//\r
-uint8 ReadByte(FILE * file)\r
-{\r
-       return (uint8)fgetc(file);\r
-}\r
-\r
-// The following routines get and put WORDs and DWORDs in little endian\r
-// format, so they should work no matter what endianess the platform that\r
-// holds the TTF object.\r
-\r
-//\r
-// Get a WORD from the current file...\r
-//\r
-uint16 ReadWord(FILE * file)\r
-{\r
-       uint16 word = (uint16)fgetc(file) << 8;\r
-       word |= (uint16)fgetc(file);\r
-\r
-       return word;\r
-}\r
-\r
-//\r
-// Get a double WORD from the current file...\r
-//\r
-uint32 ReadDWord(FILE * file)\r
-{\r
-       uint32 dword = 0;\r
-\r
-       for(int i=0; i<4; i++)\r
-       {\r
-               dword <<= 8;\r
-               dword |= (uint8)fgetc(file);\r
-       }\r
-\r
-       return dword;\r
-}\r
-\r
-//\r
-// Write a WORD to the current file...\r
-//\r
-void WriteWord(FILE * file, uint16 word)\r
-{\r
-       fputc(word >> 8, file);                                         // Hi byte\r
-       fputc(word & 0xFF, file);                                       // Lo byte\r
-}\r
-\r
-//\r
-// Write a double WORD to the current file...\r
-//\r
-void WriteDWord(FILE * file, uint32 dword)\r
-{\r
-       for(int i=0; i<4; i++)\r
-       {\r
-               fputc((char)(dword >> 24), file);\r
-               dword <<= 8;\r
-       }\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Table extraction helper routines (inline 'em?)\r
-////////////////////////////////////////////////////////////////////////////\r
-\r
-//\r
-// Return a BYTE from a BYTE based table\r
-//\r
-uint8 GetByte(uint8 * table, uint32 &ptr)\r
-{\r
-       return table[ptr++];\r
-}\r
-\r
-//\r
-// Return a WORD from a BYTE based table\r
-//\r
-uint16 GetWord(uint8 * table, uint32 &ptr)\r
-{\r
-       uint16 hi = table[ptr++];\r
-       uint16 lo = table[ptr++];\r
-\r
-       return (uint16)((hi<<8) | lo);\r
-}\r
-\r
-//\r
-// Return a double WORD from a BYTE based table\r
-//\r
-uint32 GetDWord(uint8 * table, uint32 &ptr)\r
-{\r
-       uint32 hi1 = table[ptr++];\r
-       uint32 lo1 = table[ptr++];\r
-       uint32 hi2 = table[ptr++];\r
-       uint32 lo2 = table[ptr++];\r
-\r
-       return (uint32)((hi1 << 24) | (lo1 << 16) | (hi2 << 8) | lo2);\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Table storage helper routines (inline 'em?)\r
-////////////////////////////////////////////////////////////////////////////\r
-\r
-//\r
-// Store a BYTE in a BYTE based table\r
-//\r
-void SetByte(uint8 * table, uint32 &ptr, uint8 data)\r
-{\r
-       table[ptr++] = data;\r
-}\r
-\r
-//\r
-// Store a WORD in a BYTE based table\r
-//\r
-void SetWord(uint8 * table, uint32 &ptr, uint16 data)\r
-{\r
-       table[ptr++] = data>>8;  table[ptr++] = data&0xFF;\r
-}\r
-\r
-//\r
-// Store a DWORD in a BYTE based table\r
-//\r
-void SetDWord(uint8 * table, uint32 &ptr, uint32 data)\r
-{\r
-       table[ptr++] = (uint8)(data >> 24); table[ptr++] = (uint8)(data >> 16);\r
-       table[ptr++] = (uint8)(data >> 8);  table[ptr++] = (uint8)(data & 0xFF);\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Fixed point to float (& vice versa) conversions\r
-/////////////////////////////////////////////////////////////////////////////\r
-float FixedToFloat(int16 fixed)\r
-{\r
-       return (float)fixed / 16384.0f;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// TTF Constructor\r
-/////////////////////////////////////////////////////////////////////////////\r
-TTF::TTF(void)\r
-{\r
-       loaded = false;                                                         // Set font initializer\r
-       isDirty = false;                                                        // Glyphs are clean\r
-       numberOfPolys = 0;                                                      // Set reasonable values\r
-       isCompositeGlyph = false;                                       // No composite glyph (yet)\r
-\r
-       parray[0] = &EBDT;  parray[1] = &EBLC;  parray[2] = &EBSC; // Init pointer\r
-       parray[3] = &LTSH;  parray[4] = &OS_2;  parray[5] = &PCLT; // array...\r
-       parray[6] = &VDMX;  parray[7] = &cmap;  parray[8] = &cvt; \r
-       parray[9] = &fpgm;  parray[10] = &gasp; parray[11] = &glyf;\r
-       parray[12] = &hdmx; parray[13] = &head; parray[14] = &hhea;\r
-       parray[15] = &hmtx; parray[16] = &kern; parray[17] = &loca;\r
-       parray[18] = &maxp; parray[19] = &name; parray[20] = &post;\r
-       parray[21] = &prep; parray[22] = &vhea; parray[23] = &vmtx;\r
-\r
-       larray[0] = &EBDT_len;  larray[1] = &EBLC_len;  larray[2] = &EBSC_len;\r
-       larray[3] = &LTSH_len;  larray[4] = &OS_2_len;  larray[5] = &PCLT_len;\r
-       larray[6] = &VDMX_len;  larray[7] = &cmap_len;  larray[8] = &cvt_len;\r
-       larray[9] = &fpgm_len;  larray[10] = &gasp_len; larray[11] = &glyf_len;\r
-       larray[12] = &hdmx_len; larray[13] = &head_len; larray[14] = &hhea_len;\r
-       larray[15] = &hmtx_len; larray[16] = &kern_len; larray[17] = &loca_len;\r
-       larray[18] = &maxp_len; larray[19] = &name_len; larray[20] = &post_len;\r
-       larray[21] = &prep_len; larray[22] = &vhea_len; larray[23] = &vmtx_len;\r
-\r
-       for(uint32 i=0; i<NUMTABS; i++)\r
-               *parray[i] = NULL;                                              // Init pointers...\r
-\r
-       for(uint32 i=0; i<MAXGLYPHS; i++)\r
-               glyph[i] = NULL;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// TTF Destructor\r
-/////////////////////////////////////////////////////////////////////////////\r
-TTF::~TTF()\r
-{\r
-       ClearTables();                                                          // This should handle deallocation correctly...\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: void Init(void)\r
-//\r
-// This function initializes the TTF object, setting reasonable values for\r
-// the various internal variables used by the object.\r
-// [distinct from New?]\r
-/////////////////////////////////////////////////////////////////////////////\r
-void TTF::Init(void)\r
-{\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Clear the tables so that file can be reloaded\r
-/////////////////////////////////////////////////////////////////////////////\r
-void TTF::ClearTables(void)\r
-{\r
-       for(uint32 i=0; i<NUMTABS; i++)\r
-       {\r
-               if ((*parray[i]) != NULL)\r
-               {\r
-                       free(*parray[i]);\r
-                       *parray[i] = NULL;\r
-                       *larray[i] = 0;\r
-               }\r
-       }  \r
-\r
-       for(uint32 i=0; i<MAXGLYPHS; i++)\r
-       {\r
-               if (glyph[i] != NULL)\r
-               {\r
-                       free(glyph[i]);\r
-                       glyph[i] = NULL;\r
-               }\r
-       }\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: BOOL Load(const char * filename)\r
-//\r
-// This loads the TTF database from an external file.  Returns 'true' if\r
-// successful.\r
-/////////////////////////////////////////////////////////////////////////////\r
-bool TTF::Load(const char * filename)\r
-{\r
-//     unsigned char ch;                                                       // Temp variable\r
-//     UINT num_tabs;                                                          // Number of tables\r
-       uint32 offset[NUMTABS], length[NUMTABS];        // Temporary storage...\r
-       char names[NUMTABS][5];\r
-       char narray[NUMTABS][5] = { "EBDT", "EBLC", "EBSC", "LTSH", "OS/2", "PCLT",\r
-               "VDMX", "cmap", "cvt ", "fpgm", "gasp", "glyf", "hdmx", "head", "hhea",\r
-               "hmtx", "kern", "loca", "maxp", "name", "post", "prep", "vhea", "vmtx" };\r
-\r
-       //loaded = false;\r
-//     file.open(filename, ios::binary|ios::in);       // Open the file\r
-       FILE * file = fopen(filename, "rb");\r
-\r
-       if (file == NULL)\r
-#ifdef TTFDEBUG\r
-{\r
-WriteLogMsg("Failed to open file!\n");\r
-#endif\r
-               return false;\r
-#ifdef TTFDEBUG\r
-}\r
-#endif\r
-\r
-       if (ReadDWord(file) != 0x00010000)\r
-#ifdef TTFDEBUG\r
-{\r
-WriteLogMsg("File was NOT a TTF file!\n");\r
-#endif\r
-               return false;                                                   // Not a TTF file...\r
-#ifdef TTFDEBUG\r
-}\r
-#endif\r
-\r
-       uint32 num_tabs = ReadWord(file);                       // Get # of tables\r
-#ifdef TTFDEBUG\r
-WriteLogMsg("Number of tables is %u...\n", num_tabs);\r
-#endif\r
-//     fskip(file, 6);                                                         // Skip this shiat...\r
-       fseek(file, 6, SEEK_CUR);\r
-\r
-#ifdef TTFDEBUG\r
-WriteLogMsg("Reading names of tables...\n");\r
-#endif\r
-       for(uint32 i=0; i<num_tabs; i++)\r
-       {\r
-//             ReadFile(file, names[i], 4, &bytesRead, NULL);\r
-               fread(names[i], 1, 4, file);\r
-               names[i][4] = 0;\r
-//             fskip(file, 4);                                                 // Checksum\r
-               fseek(file, 4, SEEK_CUR);                               // Checksum\r
-               offset[i] = ReadDWord(file);                    // Offset from start of file\r
-               length[i] = ReadDWord(file);                    // Length of table\r
-       }\r
-\r
-#ifdef TTFDEBUG\r
-WriteLogMsg("Reading tables...\n");\r
-#endif\r
-       for(uint32 i=0; i<num_tabs; i++)\r
-       {\r
-               for(uint32 j=0; j<NUMTABS; j++)\r
-               {\r
-                       if ((strcmp(names[i], narray[j])) == 0) // Found a match...\r
-                       {\r
-//                             *parray[j] = (uint8 *)GlobalAlloc(GMEM_FIXED, length[i]);       // Allocate space\r
-                               *parray[j] = (uint8 *)malloc(length[i]); // Alloc space\r
-\r
-                               if (*parray[j] == NULL)\r
-                                       return false;                           // Bail out if nothing allocated\r
-\r
-                               *larray[j] = length[i];                 // Set its length...\r
-//                             SetFilePointer(file, (LONG)offset[i], NULL, FILE_BEGIN);\r
-//                             ReadFile(file, *parray[j], length[i], &bytesRead, NULL);\r
-                               fseek(file, offset[i], SEEK_SET);\r
-                               fread(*parray[j], 1, length[i], file);\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-\r
-       fclose(file);\r
-\r
-// This shouldn't be necessary, since it's irrelevant (loaded flag)\r
-//    loaded = true;                       // Set 'loaded' flag...\r
-    isDirty = false;                     // Glyphs are clean\r
-    ExtractTables();                     // Move table data to my structs\r
-                                         // & ignore return val\r
-                                         // (should handle errors here)\r
-       return true;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: BOOL Save(const char * filename)\r
-//\r
-// Save the TT font currently in the object\r
-/////////////////////////////////////////////////////////////////////////////\r
-bool TTF::Save(const char * filename)\r
-{\r
-//  fstream file;\r
-//     ULONG offset = 12;\r
-       uint32 numtabs = 0;\r
-       char padding[3] = { 0, 0, 0 };\r
-       // Convert this to a table of ULONGs to decrease complexity...\r
-//wouldn't be endian safe then...\r
-       char narray[NUMTABS][5] = { "EBDT", "EBLC", "EBSC", "LTSH", "OS/2", "PCLT",\r
-               "VDMX", "cmap", "cvt ", "fpgm", "gasp", "glyf", "hdmx", "head", "hhea",\r
-               "hmtx", "kern", "loca", "maxp", "name", "post", "prep", "vhea", "vmtx" };\r
-\r
-       if (isDirty)\r
-               EncodeGlyph(currentGlyph);\r
-\r
-       BuildTables();                                                          // Ignore return value...  \r
-\r
-       for(uint32 i=0; i<NUMTABS; i++)                         // Figure out how many tables there are\r
-               if ((*parray[i]) != NULL)\r
-                       numtabs++;\r
-\r
-       uint32 offset = 12 + (numtabs * 16);            // Calc correct offset to start of data\r
-\r
-//     HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,\r
-//             NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\r
-       FILE * file = fopen(filename, "wb");\r
-\r
-       WriteDWord(file, 0x00010000);                           // Write header...\r
-       WriteWord(file, numtabs);\r
-       WriteWord(file, 0);                                                     // SearchRange (Max power of 2 <= numTables) x 16.\r
-       WriteWord(file, 0);                                                     // entrySelector Log2(max power of 2 <= numTables).\r
-       WriteWord(file, 0);                                                     // NumTables x 16 - searchRange.\r
-\r
-       for(uint32 i=0; i<NUMTABS; i++)                                 // Write out table directory...\r
-       {\r
-               if ((*parray[i]) != NULL)\r
-               {\r
-//                     for(int j=0; j<4; j++)\r
-//                             file.put(narray[i][j]);                 // Name\r
-//                     WriteFile(file, narray[i], 4, &bytesWritten, NULL);\r
-                       fwrite(narray[i], 1, 4, file);          // Name\r
-\r
-                       WriteDWord(file, 0);                            // Checksum\r
-                       WriteDWord(file, offset);                       // Offset\r
-                       WriteDWord(file, (*larray[i]));         // Length\r
-\r
-                       offset += (((*larray[i]) + 3) & ~3);    // Pad out to 4-uint8 boundary...\r
-               }\r
-       }\r
-\r
-       for(uint32 i=0; i<NUMTABS; i++)                                 // Write out the tables...\r
-       {\r
-               if ((*parray[i]) != NULL)\r
-               {\r
-//                     for(uint32 j=0; j<(*larray[i]); j++)\r
-//                             file.put((*parray[i])[j]);\r
-//                     WriteFile(file, *parray[i], *larray[i], &bytesWritten, NULL);\r
-                       fwrite(*parray[i], 1, *larray[i], file);\r
-\r
-                       uint32 remainder = ((*larray[i]) & 0x3);\r
-                       if (remainder)               // i.e., it's not evenly div by 4\r
-//                             for(j=remainder; j<4; j++)\r
-//                                     file.put((char)0);       // pad it!\r
-//                             WriteFile(file, padding, 4 - remainder, &bytesWritten, NULL);\r
-                               fwrite(padding, 1, 4 - remainder, file);\r
-               }\r
-       }\r
-\r
-       fclose(file);\r
-\r
-       return true;                                                            // Whether or not it was successful...\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: BOOL EncodeGlyph(int glyphnum)\r
-//\r
-// This function encodes the glyph data and stores it to the 'glyf' table.\r
-/////////////////////////////////////////////////////////////////////////////\r
-bool TTF::EncodeGlyph(uint16 glyphnum)\r
-{\r
-       bool retval = false;                                            // Assume failure\r
-       uint8 flag, xbuf[4000], ybuf[4000], fbuf[2000];\r
-       uint32 xp = 0, yp = 0, fp = 0;                          // Table pointers\r
-\r
-       if (glyphnum < myMaxp.numGlyphs)  // numofgls is 1 based ind, glyph# 0 based\r
-       {\r
-               // need to add composite encoding...\r
-               int lastx = 0, lasty = 0;\r
-\r
-               for(uint32 i=0; i<numberOfPoints; i++)\r
-               {\r
-                       flag = 0;\r
-                       int curx = gx[i] - lastx, cury = gy[i] - lasty;\r
-\r
-                       if (onCurve[i])\r
-                               flag |= 0x01;                                   // Set on curve info\r
-\r
-                       if (curx)\r
-                       {\r
-                               if ((curx > 255) || (curx < -255)) // I.e., it's 2 uint8 value\r
-                                       SetWord(xbuf, xp, curx);\r
-                               else\r
-                               {\r
-                                       if (curx & 0x100)\r
-                                       {\r
-                                               flag |= 0x02; // I.e., it's negative\r
-                                               curx *= -1;   // Flip it so correct value is stored\r
-                                       }\r
-                                       else\r
-                                               flag |= 0x12;\r
-\r
-                                       SetByte(xbuf, xp, curx);        // Automagically strips neg bit\r
-                               }\r
-                       }\r
-                       else\r
-                               flag |= 0x10;                                   // X-coord is same...\r
-  \r
-                       if (cury)\r
-                       {\r
-                               if ((cury > 255) || (cury < -255)) // I.e., it's 2 uint8 value\r
-                                       SetWord(ybuf, yp, cury);\r
-                               else\r
-                               {\r
-                                       if (cury & 0x100)\r
-                                       {\r
-                                               flag |= 0x04; // I.e., it's negative\r
-                                               cury *= -1;\r
-                                       }\r
-                                       else\r
-                                               flag |= 0x24;\r
-            \r
-                                       SetByte(ybuf, yp, cury);\r
-                               }\r
-                       }\r
-                       else\r
-                               flag |= 0x20;                 // Y-coord is same...\r
-  \r
-                       fbuf[i] = flag;\r
-                       lastx = gx[i];  lasty = gy[i];\r
-               }\r
-\r
-               // Now crunch flags...  ugly, ugly, ugly.\r
-/*\r
-    fbuf[numberOfPoints] = 0;  // Set sentinel value (ugly way to do this)\r
-    for(i=0; i<numberOfPoints; i++);\r
-    {\r
-      if (fbuf[i] == fbuf[i+1])  // \r
-      {\r
-        uint8 count = 0;  // Sentinel takes care of check for end of flags...\r
-        while (fbuf[i] == fbuf[++i])  count++; // Count number of repeats\r
-        i--;\r
-        fbuf[fp++] = fbuf[i] | 0x08; // Set repeat flag\r
-        fbuf[fp++] = count;          // & number of repeats\r
-      }\r
-      else  fbuf[fp++] = fbuf[i];    // Otherwise, just copy...\r
-    }\r
-*/\r
-               fp = numberOfPoints;\r
-               // Find length of glyph and reallocate space if necessary\r
-\r
-               uint32 newLength = 12 + numberOfPolys*2 + numberOfHints + fp + xp + yp;\r
-\r
-               if (newLength & 0x03)\r
-                       newLength += (4 - newLength & 0x03);\r
-\r
-               if (glyphLen[glyphnum] != newLength)\r
-               {\r
-                       glyph[glyphnum] = (uint8 *)realloc(glyph[glyphnum], newLength);\r
-                       glyphLen[glyphnum] = newLength;\r
-               }\r
-\r
-               // And finally, store it!\r
-\r
-               uint32 gp = 0;                                                  // Glyph pointer...\r
-               SetWord(glyph[glyphnum], gp, numberOfPolys);\r
-               SetWord(glyph[glyphnum], gp, llx);\r
-               SetWord(glyph[glyphnum], gp, lly);\r
-               SetWord(glyph[glyphnum], gp, urx);\r
-               SetWord(glyph[glyphnum], gp, ury);\r
-               for(uint32 i=0; i<numberOfPolys; i++)\r
-                       SetWord(glyph[glyphnum], gp, poly[i]);\r
-               SetWord(glyph[glyphnum], gp, numberOfHints);\r
-               for(uint32 i=0; i<numberOfHints; i++)\r
-                       SetByte(glyph[glyphnum], gp, hint[i]);\r
-               for(uint32 i=0; i<fp; i++)\r
-                       SetByte(glyph[glyphnum], gp, fbuf[i]);\r
-               for(uint32 i=0; i<xp; i++)\r
-                       SetByte(glyph[glyphnum], gp, xbuf[i]);\r
-               for(uint32 i=0; i<yp; i++)\r
-                       SetByte(glyph[glyphnum], gp, ybuf[i]);\r
-\r
-               retval = true;                                                  // Successfully encoded!\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: BOOL DecodeGlyph(int glyphnum)\r
-//\r
-// This function decodes the glyph data and stores it to the object's\r
-// internal array.\r
-/////////////////////////////////////////////////////////////////////////////\r
-bool TTF::DecodeGlyph(uint16 glyphnum)\r
-{\r
-       bool retval = false;\r
-       uint32 i, dp;\r
-\r
-       // glyphnum is 0 based index, while numGlyphs is 1 based\r
-       if (glyphnum >= myMaxp.numGlyphs)\r
-               return false;  // Invalid char #\r
-\r
-       if (!glyphLen[glyphnum])\r
-       {\r
-               numberOfPoints = numberOfPolys = 0;\r
-               return true;                                                    // Zero length IS valid...\r
-       }\r
-//     else                                                                            // Get character data...\r
-//     {\r
-    // Now get the character data...\r
-       dp = 0;                     // Reset data pointer\r
-       isCompositeGlyph = false;   // Default is no\r
-       numberOfPolys = GetWord(glyph[glyphnum], dp);  // # of polygons\r
-\r
-       llx = (int16)GetWord(glyph[glyphnum], dp);           // Lower left X\r
-       lly = (int16)GetWord(glyph[glyphnum], dp);           // Lower left Y\r
-       urx = (int16)GetWord(glyph[glyphnum], dp);           // Upper right X\r
-       ury = (int16)GetWord(glyph[glyphnum], dp);           // Upper right Y\r
-\r
-       // Need to handle composite glyphs better here.  The ways things\r
-       // are set now is a recipe for disaster...\r
-\r
-       if (numberOfPolys == 0xFFFF)\r
-       {\r
-               isCompositeGlyph = true;\r
-               numberOfPolys = 0;                                              // Set for no points\r
-\r
-               Composite cmpst;\r
-\r
-               while (!compositeList.IsEmpty())                // Empty composite list...\r
-                       compositeList.GetFront();\r
-\r
-               do\r
-               {\r
-                       cmpst.flags = GetWord(glyph[glyphnum], dp);\r
-                       cmpst.glyphIndex = GetWord(glyph[glyphnum], dp);\r
-                       cmpst.arg1 = (cmpst.flags & 0x01 ? (int16)GetWord(glyph[glyphnum], dp) : (int8)GetByte(glyph[glyphnum], dp));\r
-                       cmpst.arg2 = (cmpst.flags & 0x01 ? (int16)GetWord(glyph[glyphnum], dp) : (int8)GetByte(glyph[glyphnum], dp));\r
-\r
-                       if (cmpst.flags & 0x08)\r
-                               cmpst.xScale = cmpst.yScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp));\r
-                       else if (cmpst.flags & 0x40)\r
-                               cmpst.xScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)),\r
-                               cmpst.yScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp));\r
-                       else if (cmpst.flags & 0x80)\r
-                               cmpst.xScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)),\r
-                               cmpst.scale01 = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)),\r
-                               cmpst.scale10 = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)),\r
-                               cmpst.yScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp));\r
-\r
-                       compositeList.AddAtRear(cmpst);\r
-               }\r
-               while (cmpst.flags & 0x20); //*/\r
-\r
-               return true;\r
-       }\r
-\r
-//do {\r
-//     USHORT flags;\r
-//     USHORT glyphIndex;\r
-//     if ( flags & ARG_1_AND_2_ARE_uint16S) {\r
-//     (SHORT or Fuint16) argument1;\r
-//     (SHORT or Fuint16) argument2;\r
-//     } else {\r
-//             USHORT arg1and2; /* (arg1 << 8) | arg2 */\r
-//     }\r
-//     if ( flags & WE_HAVE_A_SCALE ) {\r
-//             F2Dot14  scale;    /* Format 2.14 */\r
-//     } else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE ) {\r
-//             F2Dot14  xscale;    /* Format 2.14 */\r
-//             F2Dot14  yscale;    /* Format 2.14 */\r
-//     } else if ( flags & WE_HAVE_A_TWO_BY_TWO ) {\r
-//             F2Dot14  xscale;    /* Format 2.14 */\r
-//             F2Dot14  scale01;   /* Format 2.14 */\r
-//             F2Dot14  scale10;   /* Format 2.14 */\r
-//             F2Dot14  yscale;    /* Format 2.14 */\r
-//     }\r
-//} while ( flags & MORE_COMPONENTS ) \r
-//if (flags & WE_HAVE_INSTR){\r
-//     USHORT numInstr\r
-//     uint8 instr[numInstr]\r
-//\r
-//Flags                    Bit     Description \r
-//ARG_1_AND_2_ARE_uint16S    0       If this is set, the arguments are uint16s;\r
-//                                 otherwise, they are uint8s.\r
-//ARGS_ARE_XY_VALUES       1       If this is set, the arguments are xy values;\r
-//                                 otherwise, they are points.\r
-//ROUND_XY_TO_GRID         2       For the xy values if the preceding is true.\r
-//WE_HAVE_A_SCALE          3       This indicates that there is a simple scale\r
-//                                 for the component. Otherwise, scale = 1.0.\r
-//RESERVED                 4       This bit is reserved.  Set it to 0. \r
-//MORE_COMPONENTS          5       Indicates at least one more glyph after this\r
-//                                 one.\r
-//WE_HAVE_AN_X_AND_Y_SCALE 6       The x direction will use a different scale\r
-//                                 from the y direction.\r
-//WE_HAVE_A_TWO_BY_TWO     7       There is a 2 by 2 transformation that will\r
-//                                 be used to scale the component.\r
-//WE_HAVE_INSTRUCTIONS     8       Following the last component are\r
-//                                 instructions for the composite character.\r
-//USE_MY_METRICS           9       If set, this forces the aw and lsb (and rsb)\r
-//                                 for the composite to be equal to those from\r
-//                                 this original glyph. This works for hinted\r
-//                                 and unhinted characters.\r
-\r
-       for(i=0; i<numberOfPolys; i++)\r
-               poly[i] = GetWord(glyph[glyphnum], dp);\r
-\r
-       numberOfHints = GetWord(glyph[glyphnum], dp);\r
-\r
-       for(i=0; i<numberOfHints; i++)\r
-               hint[i] = GetByte(glyph[glyphnum], dp);\r
-\r
-       // Decode the dots...\r
-\r
-       uint32 num_pts = poly[numberOfPolys-1] + 1;\r
-       numberOfPoints = num_pts; // necessary??\r
-       uint32 xptr, yptr;        // pointers to beginning of coord data\r
-       uint32 numXs = 0;\r
-       int xx = 0, yy = 0, repeat;\r
-       uint32 numTokens = num_pts, k, numRep;\r
-\r
-       // We make an educated guess that num_pts = num_tokens; but if there\r
-       // is repeated data in the tokens, then we need to adjust the # of\r
-       // tokens down appropriately.\r
-\r
-       for(uint32 i=0; i<numTokens; i++)\r
-       {\r
-               uint8 token = glyph[glyphnum][dp+i];  uint32 rpts = 1;\r
-\r
-               if (token & 0x08)      // Repeated token?\r
-               {\r
-                       i++;                 // Yes, bump pointer to # of times to repeat\r
-                       numRep = glyph[glyphnum][dp+i];\r
-                       rpts += numRep;\r
-\r
-                       if (numRep > 1)      // Do we need to adjust numTokens?\r
-   // this is bad, modifying numTokens while it's used as a compare value\r
-   // in the above loop...\r
-   // Is it necessary to do so in order to keep from going too far?\r
-                       numTokens -= (numRep - 1); // Yes, adjust.\r
-               }\r
-\r
-               // 10 = same x(0uint8s), 00 = 2uint8s, 02&12 = 1uint8\r
-               if ((token & 0x02) == 0x02)\r
-                       numXs += rpts;\r
-\r
-               if ((token & 0x12) == 0x00)\r
-                       numXs += (rpts*2);\r
-       }\r
-\r
-       xptr = dp + numTokens;\r
-       yptr = dp + numTokens + numXs;\r
-\r
-       // & continue decoding X/Y-coords...\r
-\r
-       k = 0;                               // Index to the point array\r
-\r
-       for(uint32 i=0; i<numTokens; i++)\r
-       {\r
-               uint8 token = glyph[glyphnum][dp+i];\r
-               repeat = 1;\r
-\r
-               if (token & 0x08)\r
-               {\r
-                       i++;\r
-                       repeat += glyph[glyphnum][dp+i]; // Set repeat data...\r
-               }\r
-\r
-               while (repeat--)\r
-               {\r
-                       if ((token & 0x12) == 0x12)\r
-                               xx += GetByte(glyph[glyphnum], xptr);\r
-\r
-                       if ((token & 0x12) == 0x02)\r
-                               xx -= GetByte(glyph[glyphnum], xptr);\r
-\r
-                       if ((token & 0x12) == 0x00)\r
-                               xx += (int16)GetWord(glyph[glyphnum], xptr);\r
-\r
-                       gx[k] = xx;                      // Store x-coordinate\r
-\r
-                       if ((token & 0x24) == 0x24)\r
-                               yy += GetByte(glyph[glyphnum], yptr);\r
-\r
-                       if ((token & 0x24) == 0x04)\r
-                               yy -= GetByte(glyph[glyphnum], yptr);\r
-\r
-                       if ((token & 0x24) == 0x00)\r
-                               yy += (int16)GetWord(glyph[glyphnum], yptr);\r
-\r
-                       gy[k] = yy;                      // Store y-coordinate\r
-\r
-                       onCurve[k++] = (token & 0x01 ? true : false);  // If bit 0 set, then it's on curve\r
-               }\r
-       }\r
-\r
-       retval = true;                                                  // Hmm. Successfully decoded a glyph...\r
-//     }\r
-\r
-       isDirty = false;  // do it here?\r
-\r
-       return retval;\r
-}\r
-\r
-/*****************************************************************************\r
- Member function:\r
-\r
- This function decodes the 'glyf' data for a non-composite (atomic) glyph and\r
- returns it as a GlyphPoints object. Helper function.\r
- *****************************************************************************/\r
-GlyphPoints TTF::GetGlyphPoints(uint16 glyphNum)\r
-{\r
-       if (DecodeGlyph(glyphNum))\r
-               return GlyphPoints(numberOfPoints, numberOfPolys, gx, gy, onCurve, poly);\r
-\r
-       return GlyphPoints();\r
-}\r
-\r
-/*****************************************************************************\r
- Member function:\r
-\r
- This function decodes the 'glyf' data for a composite glyph and returns\r
- it as a GlyphPoints object.\r
- *****************************************************************************/\r
-GlyphPoints TTF::GetAllCompositePoints(uint16 glyphNum)\r
-{\r
-//  int tmpGlyph = currentGlyph;\r
-  \r
-       DecodeGlyph(glyphNum);         // Check for composite-ness\r
-\r
-       if (!isCompositeGlyph)\r
-               return GlyphPoints();\r
-\r
-/*\r
-  for(int i=1; i<=pDoc->m_myFont.compositeList.Length(); i++)\r
-  {\r
-    TComposite cmpst = fnt->compositeList.PeekPosition(i);\r
-    fnt->SetGlyph(cmpst.glyphIndex);\r
-    if (cmpst.flags & 0x0002)\r
-      m_nXOffset = cmpst.arg1, m_nYOffset = cmpst.arg2;\r
-    ScanConvertSingleGlyph(pDC, nScanlines, nHorzLines, nXOffset, nYOffset);\r
-  }\r
-  fnt->SetGlyph(pDoc->character_num);\r
-*/\r
-\r
-       GlyphPoints retVal;\r
-\r
-       for(int i=1; i<=compositeList.Length(); i++)\r
-       {\r
-               Composite cmpst = compositeList.PeekPosition(i);\r
-    \r
-//    SetGlyph(cmpst.glyphIndex);\r
-//    if (cmpst.flags & 0x0002)\r
-//      m_nXOffset = cmpst.arg1, m_nYOffset = cmpst.arg2;\r
-//    ScanConvertSingleGlyph(pDC, nScanlines, nHorzLines, nXOffset, nYOffset);\r
-               GlyphPoints gp = GetGlyphPoints(cmpst.glyphIndex);\r
-\r
-               if (cmpst.flags & 0x0002)\r
-                       gp.OffsetPoints(cmpst.arg1, cmpst.arg2);\r
-\r
-               retVal = retVal + gp;\r
-               // NOTE: May have to adjust scanlines as per 0x0002 above...\r
-       }\r
-\r
-//  SetGlyph(tmpGlyph);\r
-       DecodeGlyph(currentGlyph);     // Reset needed here...\r
-\r
-       return retVal;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: void GetCharName(int cNum, uint8 * buf)\r
-//\r
-// This function returns the character name of the glyph number passed in.\r
-/////////////////////////////////////////////////////////////////////////////\r
-void TTF::GetCharName(int cNum, uint8 * buf)\r
-{\r
-       buf[0] = 0;                                                                     // Set failure as default condition\r
-  \r
-       if (!post)                                                                      // PS names are here...\r
-               return;\r
-\r
-       if (post[1] != 0x02 || post[2] != 0x00)         // i.e., it's NOT a V2.0 table\r
-               return;\r
-\r
-       uint8 * pTab = NULL;\r
-       uint32 tabOff = 34, numGlyphs = (uint32)((post[32] << 8) | post[33]);\r
-       uint32 index = (uint32)((post[tabOff + cNum * 2] << 8) | post[tabOff + cNum * 2 + 1]);\r
-       uint32 nInd2;\r
-\r
-       if (index > 257)\r
-       {\r
-               index -= 258;\r
-               nInd2 = tabOff + (2 * numGlyphs);\r
-               pTab = post;\r
-       }\r
-       else\r
-       {\r
-               nInd2 = 0;\r
-               pTab = macStdNames;\r
-       }\r
-\r
-       for(uint32 i=0; i<index; i++)\r
-               nInd2 = nInd2 + pTab[nInd2] + 1; // 1st uint8 is length of string + that uint8\r
-\r
-       uint8 len = pTab[nInd2];\r
-       nInd2++;\r
-\r
-       for(uint8 i=0; i<len; i++)\r
-               buf[i] = pTab[nInd2 + i];\r
-\r
-       buf[len] = 0;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: BOOL ExtractTables(void)\r
-//\r
-// This function extracts the data from the various tables and puts them in\r
-// various structs for easier handling of the font data.\r
-/////////////////////////////////////////////////////////////////////////////\r
-bool TTF::ExtractTables(void)\r
-{\r
-       if (head_len != 54)\r
-       {\r
-#ifdef TTFDEBUG\r
-WriteLogMsg("Bad HEAD header: Expected 54, found %u...\n", head_len);\r
-#endif\r
-               return false;                                                   // Corrupt data?\r
-       }\r
-\r
-       uint32 tp = 0;\r
-       myHead.version            = GetDWord(head, tp);\r
-       myHead.fontRevision       = GetDWord(head, tp);\r
-       myHead.checkSumAdjustment = GetDWord(head, tp);\r
-       myHead.magicNumber        = GetDWord(head, tp);\r
-       myHead.flags              = GetWord(head, tp);\r
-       myHead.unitsPerEm         = GetWord(head, tp);\r
-       myHead.createdh           = GetDWord(head, tp);\r
-       myHead.createdl           = GetDWord(head, tp);\r
-       myHead.modifiedh          = GetDWord(head, tp);\r
-       myHead.modifiedl          = GetDWord(head, tp);\r
-       myHead.xMin               = GetWord(head, tp);\r
-       myHead.yMin               = GetWord(head, tp);\r
-       myHead.xMax               = GetWord(head, tp);\r
-       myHead.yMax               = GetWord(head, tp);\r
-       myHead.macStyle           = GetWord(head, tp);\r
-       myHead.lowestRecPPEM      = GetWord(head, tp);\r
-       myHead.fontDirectionHint  = (int16)GetWord(head, tp);\r
-       myHead.indexToLocFormat   = (int16)GetWord(head, tp);\r
-       myHead.glyphDataFormat    = (int16)GetWord(head, tp);\r
-\r
-       if (maxp_len != 32)\r
-       {\r
-#ifdef TDEBUG\r
-WriteLogMsg("Bad MAXP header: Expected 32, found %u...\n", maxp_len);\r
-#endif\r
-               return false;                                                   // Corrupt data?\r
-       }\r
-\r
-       tp = 0;                                                                         // Reset table pointer\r
-       myMaxp.version               = GetDWord(maxp, tp);\r
-       myMaxp.numGlyphs             = GetWord(maxp, tp);\r
-       myMaxp.maxPoints             = GetWord(maxp, tp);\r
-       myMaxp.maxContours           = GetWord(maxp, tp);\r
-       myMaxp.maxCompositePoints    = GetWord(maxp, tp);\r
-       myMaxp.maxCompositeContours  = GetWord(maxp, tp);\r
-       myMaxp.maxZones              = GetWord(maxp, tp);\r
-       myMaxp.maxTwilightPoints     = GetWord(maxp, tp);\r
-       myMaxp.maxStorage            = GetWord(maxp, tp);\r
-       myMaxp.maxFunctionDefs       = GetWord(maxp, tp);\r
-       myMaxp.maxInstructionDefs    = GetWord(maxp, tp);\r
-       myMaxp.maxStackElements      = GetWord(maxp, tp);\r
-       myMaxp.maxSizeOfInstructions = GetWord(maxp, tp);\r
-       myMaxp.maxComponentElements  = GetWord(maxp, tp);\r
-       myMaxp.maxComponentDepth     = GetWord(maxp, tp);\r
-\r
-       tp = 0;                                                                         // Reset table pointer\r
-       uint32 start = (myHead.indexToLocFormat ? GetDWord(loca, tp) : GetWord(loca, tp) << 1);\r
-\r
-       for(uint32 i=0; i<myMaxp.numGlyphs; i++)\r
-       {\r
-               uint32 end = (myHead.indexToLocFormat ? GetDWord(loca, tp) : GetWord(loca, tp) << 1);\r
-               uint32 length = end - start;\r
-               glyphLen[i] = length;                                   // Lengths are saved 'cause malloc is sloppy\r
-\r
-               if (length)     // loca+start? pointer arithmetic?\r
-               {\r
-                       glyph[i] = (uint8 *)malloc(length);     // Allocate space,\r
-                       memcpy(glyph[i], glyf+start, length);   // and move it!\r
-               }\r
-               else\r
-                       glyph[i] = NULL;\r
-\r
-               start = end;                                                    // Reset start value\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: BOOL BuildTables(void)\r
-//\r
-// This function builds the various TTF tables using info in the various\r
-// structs so that a TTF file can be written out to disk.\r
-/////////////////////////////////////////////////////////////////////////////\r
-bool TTF::BuildTables(void)\r
-{\r
-       uint32 i, tp, start;\r
-\r
-       myHead.indexToLocFormat = 1;                            // We don't bother with [uint16s*2] format...\r
-\r
-       // Build HEAD table\r
-\r
-       tp = 0;                                                                         // Reset table pointer\r
-       SetDWord(head, tp, myHead.version);//            = GetDWord(head, tp);\r
-       SetDWord(head, tp, myHead.fontRevision);//       = GetDWord(head, tp);\r
-       SetDWord(head, tp, myHead.checkSumAdjustment);// = GetDWord(head, tp);\r
-       SetDWord(head, tp, myHead.magicNumber);//        = GetDWord(head, tp);\r
-       SetWord(head, tp, myHead.flags);//              = GetWord(head, tp);\r
-       SetWord(head, tp, myHead.unitsPerEm);//         = GetWord(head, tp);\r
-       SetDWord(head, tp, myHead.createdh);//           = GetDWord(head, tp);\r
-       SetDWord(head, tp, myHead.createdl);//           = GetDWord(head, tp);\r
-       SetDWord(head, tp, myHead.modifiedh);//          = GetDWord(head, tp);\r
-       SetDWord(head, tp, myHead.modifiedl);//          = GetDWord(head, tp);\r
-       SetWord(head, tp, myHead.xMin);//               = GetWord(head, tp);\r
-       SetWord(head, tp, myHead.yMin);//               = GetWord(head, tp);\r
-       SetWord(head, tp, myHead.xMax);//               = GetWord(head, tp);\r
-       SetWord(head, tp, myHead.yMax);//               = GetWord(head, tp);\r
-       SetWord(head, tp, myHead.macStyle);//           = GetWord(head, tp);\r
-       SetWord(head, tp, myHead.lowestRecPPEM);//      = GetWord(head, tp);\r
-       SetWord(head, tp, myHead.fontDirectionHint);//  = (int16)GetWord(head, tp);\r
-       SetWord(head, tp, myHead.indexToLocFormat);//   = (int16)GetWord(head, tp);\r
-       SetWord(head, tp, myHead.glyphDataFormat);//    = (int16)GetWord(head, tp);\r
-\r
-       // Build MAXP table\r
-\r
-       tp = 0;                                                                         // Reset table pointer\r
-       SetDWord(maxp, tp, myMaxp.version);//               = GetDWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.numGlyphs);//             = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxPoints);//             = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxContours);//           = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxCompositePoints);//    = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxCompositeContours);//  = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxZones);//              = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxTwilightPoints);//     = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxStorage);//            = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxFunctionDefs);//       = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxInstructionDefs);//    = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxStackElements);//      = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxSizeOfInstructions);// = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxComponentElements);//  = GetWord(maxp, tp);\r
-       SetWord(maxp, tp, myMaxp.maxComponentDepth);//     = GetWord(maxp, tp);\r
-\r
-       // Build LOCA & GLYF tables\r
-\r
-       loca_len = (myMaxp.numGlyphs+1) * 4;            // Set size of table\r
-\r
-       if (loca)\r
-               free(loca);                                                             // And create/reallocate it...\r
-\r
-       loca = (uint8 *) malloc(loca_len);\r
-\r
-       glyf_len = 0;                                                           // Refigure glyf table length\r
-\r
-       for(i=0; i<myMaxp.numGlyphs; i++)\r
-               glyf_len += glyphLen[i];\r
-\r
-       if (glyf)\r
-               free(glyf);\r
-\r
-       glyf = (uint8 *) malloc(glyf_len);\r
-\r
-       start = tp = 0;                                                         // Reset table pointer\r
-\r
-       for(i=0; i<myMaxp.numGlyphs; i++)\r
-       {\r
-               SetDWord(loca, tp, start);                              // Store glyph start address\r
-\r
-               if (glyphLen[i])\r
-                       memcpy(glyf+start, glyph[i], glyphLen[i]);\r
-\r
-               start += glyphLen[i];\r
-       }\r
-\r
-       SetDWord(loca, tp, start);                                      // Finally, store end of glyphs+1\r
-\r
-       return true;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: BOOL SetGlyph(int glyphnum)\r
-//\r
-// This function decodes the glyph data and stores the points in its own\r
-// internal array.  If the flag isDirty is set, it also encodes the internal\r
-// array and stores it to the 'glyf' table.\r
-/////////////////////////////////////////////////////////////////////////////\r
-bool TTF::SetGlyph(uint16 glyphnum)\r
-{\r
-       bool retval = false;                                            // Set failure as default\r
-\r
-       if (isDirty)\r
-               EncodeGlyph(currentGlyph);\r
-\r
-       isDirty = false;\r
-\r
-       if (glyphnum < myMaxp.numGlyphs)                        // numofgls is 1 based ind, glyph# 0 based\r
-       {\r
-               currentGlyph = glyphnum;\r
-               DecodeGlyph(currentGlyph);\r
-               retval = true;\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: BOOL AddGlyph(int glyphnum)\r
-//\r
-// This function adds a glyph of zero size at position glyphnum.  If glyphnum\r
-// is greater than the number of glyphs, glyph is added at end of list. This\r
-// glyph then becomes the current glyph.\r
-/////////////////////////////////////////////////////////////////////////////\r
-bool TTF::AddGlyph(uint16 glyphnum)\r
-{\r
-       // incomplete: JLH\r
-       bool retval = false;\r
-\r
-       if (isDirty)\r
-               EncodeGlyph(currentGlyph);\r
-\r
-       isDirty = false;\r
-\r
-       return retval;\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Member function: BOOL DeleteGlyph(int glyphnum)\r
-//\r
-// This function deletes the glyph at position glyphnum.  All glyphs after\r
-// this glyph are moved down in position.\r
-/////////////////////////////////////////////////////////////////////////////\r
-bool TTF::DeleteGlyph(uint16 glyphnum)\r
-{\r
-       // incomplete: JLH\r
-       bool retval = false;\r
-\r
-       return retval;\r
-}\r
-\r
-//\r
-// Various & sundry member functions implementation\r
-//\r
-// NOTE: For error handling, should throw exceptions--not return values...! !!! FIX !!!\r
-//\r
-\r
-Box TTF::GetBoundingBox(void)\r
-{\r
-       return Box(llx, lly, urx, ury);\r
-}\r
-\r
-GlyphPt TTF::GetPoint(uint16 pointno)\r
-{\r
-       GlyphPt p;\r
-\r
-       if (pointno >= MAXPOINTS)\r
-               return p; // Fix to make invalid\r
-\r
-       p.x = gx[pointno], p.y = gy[pointno], p.onCurve = onCurve[pointno];\r
-       return p;\r
-}\r
-\r
-uint16 TTF::GetNumberOfPolys(void)\r
-{\r
-       return numberOfPolys;\r
-}\r
-\r
-uint16 TTF::GetPolyEnd(uint16 polynum)\r
-{\r
-       if (polynum >= numberOfPolys)\r
-               return 0;\r
-\r
-       return poly[polynum];\r
-}\r
-\r
-int TTF::GetPointX(uint16 pointno)\r
-{\r
-       if (pointno >= MAXPOINTS)\r
-               return 0;\r
-\r
-       return gx[pointno];\r
-}\r
-\r
-int TTF::GetPointY(uint16 pointno)\r
-{\r
-       if (pointno >= MAXPOINTS)\r
-               return 0;\r
-\r
-       return gy[pointno];\r
-}\r
-\r
-bool TTF::GetOnCurve(uint16 pointno)\r
-{\r
-       if (pointno >= MAXPOINTS)\r
-               return true;\r
-\r
-       return onCurve[pointno];\r
-}\r
-\r
-bool TTF::SetOnCurve(uint16 pointno, bool state)\r
-{\r
-       if (pointno >= numberOfPoints)\r
-               return false;\r
-\r
-       onCurve[pointno] = state;\r
-       isDirty = true;\r
-\r
-       return true;\r
-}\r
-\r
-bool TTF::MovePoint(uint16 pointno, int x, int y)\r
-{\r
-       if (pointno >= numberOfPoints)\r
-               return false;\r
-\r
-       gx[pointno] = x;  gy[pointno] = y;\r
-       isDirty = true;\r
-\r
-       return true;\r
-}\r
-\r
-bool TTF::MovePoint(uint16 pointno, GlyphPt p)\r
-{\r
-       if (pointno >= numberOfPoints)\r
-               return false;\r
-\r
-       gx[pointno] = p.x;  gy[pointno] = p.y;  onCurve[pointno] = p.onCurve;\r
-       isDirty = true;\r
-\r
-       return true;\r
-}\r
-\r
-bool TTF::IsCompositeGlyph(void)\r
-{\r
-       return isCompositeGlyph;\r
-}\r
-\r
+//
+// TTF.CPP - The TrueType class
+// by James L. Hammons
+// (C) 2005 Underground Software
+//
+// This class encapsulates all the complexity of a TrueType Font File
+// database.  Included are functions to load, save, & initialize the
+// TTF database, move, add, & delete points & glyphs, i.e. manipulate
+// a TTF file in just about any way imaginable!
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  ??/??/199?  Created this file
+//
+//
+// STILL TO BE DONE:
+//
+// - Eliminate ALL references to BYTE, WORD, SBYTE, SWORD, etc.
+//
+
+#include <stdio.h>                                                             // For file handling, etc.                                                                                              //
+#include <stdlib.h>
+#include <string.h>
+#include "charnames.h"
+#include "ttf.h"
+
+#define TTFDEBUG
+
+#ifdef TTFDEBUG
+#include "debug.h"
+#endif
+
+#define NUMTABS  24                   // Number of distinct tables
+
+
+/*void fskip(HANDLE file, uint32 bytesToSkip)
+{
+       SetFilePointer(file, (LONG)bytesToSkip, NULL, FILE_CURRENT);
+}*/
+
+//
+// Get a BYTE from the current file...
+//
+uint8 ReadByte(FILE * file)
+{
+       return (uint8)fgetc(file);
+}
+
+// The following routines get and put WORDs and DWORDs in little endian
+// format, so they should work no matter what endianess the platform that
+// holds the TTF object.
+
+//
+// Get a WORD from the current file...
+//
+uint16 ReadWord(FILE * file)
+{
+       uint16 word = (uint16)fgetc(file) << 8;
+       word |= (uint16)fgetc(file);
+
+       return word;
+}
+
+//
+// Get a double WORD from the current file...
+//
+uint32 ReadDWord(FILE * file)
+{
+       uint32 dword = 0;
+
+       for(int i=0; i<4; i++)
+       {
+               dword <<= 8;
+               dword |= (uint8)fgetc(file);
+       }
+
+       return dword;
+}
+
+//
+// Write a WORD to the current file...
+//
+void WriteWord(FILE * file, uint16 word)
+{
+       fputc(word >> 8, file);                                         // Hi byte
+       fputc(word & 0xFF, file);                                       // Lo byte
+}
+
+//
+// Write a double WORD to the current file...
+//
+void WriteDWord(FILE * file, uint32 dword)
+{
+       for(int i=0; i<4; i++)
+       {
+               fputc((char)(dword >> 24), file);
+               dword <<= 8;
+       }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Table extraction helper routines (inline 'em?)
+////////////////////////////////////////////////////////////////////////////
+
+//
+// Return a BYTE from a BYTE based table
+//
+uint8 GetByte(uint8 * table, uint32 &ptr)
+{
+       return table[ptr++];
+}
+
+//
+// Return a WORD from a BYTE based table
+//
+uint16 GetWord(uint8 * table, uint32 &ptr)
+{
+       uint16 hi = table[ptr++];
+       uint16 lo = table[ptr++];
+
+       return (uint16)((hi<<8) | lo);
+}
+
+//
+// Return a double WORD from a BYTE based table
+//
+uint32 GetDWord(uint8 * table, uint32 &ptr)
+{
+       uint32 hi1 = table[ptr++];
+       uint32 lo1 = table[ptr++];
+       uint32 hi2 = table[ptr++];
+       uint32 lo2 = table[ptr++];
+
+       return (uint32)((hi1 << 24) | (lo1 << 16) | (hi2 << 8) | lo2);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Table storage helper routines (inline 'em?)
+////////////////////////////////////////////////////////////////////////////
+
+//
+// Store a BYTE in a BYTE based table
+//
+void SetByte(uint8 * table, uint32 &ptr, uint8 data)
+{
+       table[ptr++] = data;
+}
+
+//
+// Store a WORD in a BYTE based table
+//
+void SetWord(uint8 * table, uint32 &ptr, uint16 data)
+{
+       table[ptr++] = data>>8;  table[ptr++] = data&0xFF;
+}
+
+//
+// Store a DWORD in a BYTE based table
+//
+void SetDWord(uint8 * table, uint32 &ptr, uint32 data)
+{
+       table[ptr++] = (uint8)(data >> 24); table[ptr++] = (uint8)(data >> 16);
+       table[ptr++] = (uint8)(data >> 8);  table[ptr++] = (uint8)(data & 0xFF);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Fixed point to float (& vice versa) conversions
+/////////////////////////////////////////////////////////////////////////////
+float FixedToFloat(int16 fixed)
+{
+       return (float)fixed / 16384.0f;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// TTF Constructor
+/////////////////////////////////////////////////////////////////////////////
+TTF::TTF(void)
+{
+       loaded = false;                                                         // Set font initializer
+       isDirty = false;                                                        // Glyphs are clean
+       numberOfPolys = 0;                                                      // Set reasonable values
+       isCompositeGlyph = false;                                       // No composite glyph (yet)
+
+       parray[0] = &EBDT;  parray[1] = &EBLC;  parray[2] = &EBSC; // Init pointer
+       parray[3] = &LTSH;  parray[4] = &OS_2;  parray[5] = &PCLT; // array...
+       parray[6] = &VDMX;  parray[7] = &cmap;  parray[8] = &cvt; 
+       parray[9] = &fpgm;  parray[10] = &gasp; parray[11] = &glyf;
+       parray[12] = &hdmx; parray[13] = &head; parray[14] = &hhea;
+       parray[15] = &hmtx; parray[16] = &kern; parray[17] = &loca;
+       parray[18] = &maxp; parray[19] = &name; parray[20] = &post;
+       parray[21] = &prep; parray[22] = &vhea; parray[23] = &vmtx;
+
+       larray[0] = &EBDT_len;  larray[1] = &EBLC_len;  larray[2] = &EBSC_len;
+       larray[3] = &LTSH_len;  larray[4] = &OS_2_len;  larray[5] = &PCLT_len;
+       larray[6] = &VDMX_len;  larray[7] = &cmap_len;  larray[8] = &cvt_len;
+       larray[9] = &fpgm_len;  larray[10] = &gasp_len; larray[11] = &glyf_len;
+       larray[12] = &hdmx_len; larray[13] = &head_len; larray[14] = &hhea_len;
+       larray[15] = &hmtx_len; larray[16] = &kern_len; larray[17] = &loca_len;
+       larray[18] = &maxp_len; larray[19] = &name_len; larray[20] = &post_len;
+       larray[21] = &prep_len; larray[22] = &vhea_len; larray[23] = &vmtx_len;
+
+       for(uint32 i=0; i<NUMTABS; i++)
+               *parray[i] = NULL;                                              // Init pointers...
+
+       for(uint32 i=0; i<MAXGLYPHS; i++)
+               glyph[i] = NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// TTF Destructor
+/////////////////////////////////////////////////////////////////////////////
+TTF::~TTF()
+{
+       ClearTables();                                                          // This should handle deallocation correctly...
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: void Init(void)
+//
+// This function initializes the TTF object, setting reasonable values for
+// the various internal variables used by the object.
+// [distinct from New?]
+/////////////////////////////////////////////////////////////////////////////
+void TTF::Init(void)
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Clear the tables so that file can be reloaded
+/////////////////////////////////////////////////////////////////////////////
+void TTF::ClearTables(void)
+{
+       for(uint32 i=0; i<NUMTABS; i++)
+       {
+               if ((*parray[i]) != NULL)
+               {
+                       free(*parray[i]);
+                       *parray[i] = NULL;
+                       *larray[i] = 0;
+               }
+       }  
+
+       for(uint32 i=0; i<MAXGLYPHS; i++)
+       {
+               if (glyph[i] != NULL)
+               {
+                       free(glyph[i]);
+                       glyph[i] = NULL;
+               }
+       }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: BOOL Load(const char * filename)
+//
+// This loads the TTF database from an external file.  Returns 'true' if
+// successful.
+/////////////////////////////////////////////////////////////////////////////
+bool TTF::Load(const char * filename)
+{
+//     unsigned char ch;                                                       // Temp variable
+//     UINT num_tabs;                                                          // Number of tables
+       uint32 offset[NUMTABS], length[NUMTABS];        // Temporary storage...
+       char names[NUMTABS][5];
+       char narray[NUMTABS][5] = { "EBDT", "EBLC", "EBSC", "LTSH", "OS/2", "PCLT",
+               "VDMX", "cmap", "cvt ", "fpgm", "gasp", "glyf", "hdmx", "head", "hhea",
+               "hmtx", "kern", "loca", "maxp", "name", "post", "prep", "vhea", "vmtx" };
+
+       //loaded = false;
+//     file.open(filename, ios::binary|ios::in);       // Open the file
+       FILE * file = fopen(filename, "rb");
+
+       if (file == NULL)
+#ifdef TTFDEBUG
+{
+WriteLogMsg("Failed to open file!\n");
+#endif
+               return false;
+#ifdef TTFDEBUG
+}
+#endif
+
+       if (ReadDWord(file) != 0x00010000)
+#ifdef TTFDEBUG
+{
+WriteLogMsg("File was NOT a TTF file!\n");
+#endif
+               return false;                                                   // Not a TTF file...
+#ifdef TTFDEBUG
+}
+#endif
+
+       uint32 num_tabs = ReadWord(file);                       // Get # of tables
+#ifdef TTFDEBUG
+WriteLogMsg("Number of tables is %u...\n", num_tabs);
+#endif
+//     fskip(file, 6);                                                         // Skip this shiat...
+       fseek(file, 6, SEEK_CUR);
+
+#ifdef TTFDEBUG
+WriteLogMsg("Reading names of tables...\n");
+#endif
+       for(uint32 i=0; i<num_tabs; i++)
+       {
+//             ReadFile(file, names[i], 4, &bytesRead, NULL);
+               fread(names[i], 1, 4, file);
+               names[i][4] = 0;
+//             fskip(file, 4);                                                 // Checksum
+               fseek(file, 4, SEEK_CUR);                               // Checksum
+               offset[i] = ReadDWord(file);                    // Offset from start of file
+               length[i] = ReadDWord(file);                    // Length of table
+       }
+
+#ifdef TTFDEBUG
+WriteLogMsg("Reading tables...\n");
+#endif
+       for(uint32 i=0; i<num_tabs; i++)
+       {
+               for(uint32 j=0; j<NUMTABS; j++)
+               {
+                       if ((strcmp(names[i], narray[j])) == 0) // Found a match...
+                       {
+//                             *parray[j] = (uint8 *)GlobalAlloc(GMEM_FIXED, length[i]);       // Allocate space
+                               *parray[j] = (uint8 *)malloc(length[i]); // Alloc space
+
+                               if (*parray[j] == NULL)
+                                       return false;                           // Bail out if nothing allocated
+
+                               *larray[j] = length[i];                 // Set its length...
+//                             SetFilePointer(file, (LONG)offset[i], NULL, FILE_BEGIN);
+//                             ReadFile(file, *parray[j], length[i], &bytesRead, NULL);
+                               fseek(file, offset[i], SEEK_SET);
+                               fread(*parray[j], 1, length[i], file);
+                               break;
+                       }
+               }
+       }
+
+       fclose(file);
+
+// This shouldn't be necessary, since it's irrelevant (loaded flag)
+//    loaded = true;                       // Set 'loaded' flag...
+    isDirty = false;                     // Glyphs are clean
+    ExtractTables();                     // Move table data to my structs
+                                         // & ignore return val
+                                         // (should handle errors here)
+       return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: BOOL Save(const char * filename)
+//
+// Save the TT font currently in the object
+/////////////////////////////////////////////////////////////////////////////
+bool TTF::Save(const char * filename)
+{
+//  fstream file;
+//     ULONG offset = 12;
+       uint32 numtabs = 0;
+       char padding[3] = { 0, 0, 0 };
+       // Convert this to a table of ULONGs to decrease complexity...
+//wouldn't be endian safe then...
+       char narray[NUMTABS][5] = { "EBDT", "EBLC", "EBSC", "LTSH", "OS/2", "PCLT",
+               "VDMX", "cmap", "cvt ", "fpgm", "gasp", "glyf", "hdmx", "head", "hhea",
+               "hmtx", "kern", "loca", "maxp", "name", "post", "prep", "vhea", "vmtx" };
+
+       if (isDirty)
+               EncodeGlyph(currentGlyph);
+
+       BuildTables();                                                          // Ignore return value...  
+
+       for(uint32 i=0; i<NUMTABS; i++)                         // Figure out how many tables there are
+               if ((*parray[i]) != NULL)
+                       numtabs++;
+
+       uint32 offset = 12 + (numtabs * 16);            // Calc correct offset to start of data
+
+//     HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+//             NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+       FILE * file = fopen(filename, "wb");
+
+       WriteDWord(file, 0x00010000);                           // Write header...
+       WriteWord(file, numtabs);
+       WriteWord(file, 0);                                                     // SearchRange (Max power of 2 <= numTables) x 16.
+       WriteWord(file, 0);                                                     // entrySelector Log2(max power of 2 <= numTables).
+       WriteWord(file, 0);                                                     // NumTables x 16 - searchRange.
+
+       for(uint32 i=0; i<NUMTABS; i++)                                 // Write out table directory...
+       {
+               if ((*parray[i]) != NULL)
+               {
+//                     for(int j=0; j<4; j++)
+//                             file.put(narray[i][j]);                 // Name
+//                     WriteFile(file, narray[i], 4, &bytesWritten, NULL);
+                       fwrite(narray[i], 1, 4, file);          // Name
+
+                       WriteDWord(file, 0);                            // Checksum
+                       WriteDWord(file, offset);                       // Offset
+                       WriteDWord(file, (*larray[i]));         // Length
+
+                       offset += (((*larray[i]) + 3) & ~3);    // Pad out to 4-uint8 boundary...
+               }
+       }
+
+       for(uint32 i=0; i<NUMTABS; i++)                                 // Write out the tables...
+       {
+               if ((*parray[i]) != NULL)
+               {
+//                     for(uint32 j=0; j<(*larray[i]); j++)
+//                             file.put((*parray[i])[j]);
+//                     WriteFile(file, *parray[i], *larray[i], &bytesWritten, NULL);
+                       fwrite(*parray[i], 1, *larray[i], file);
+
+                       uint32 remainder = ((*larray[i]) & 0x3);
+                       if (remainder)               // i.e., it's not evenly div by 4
+//                             for(j=remainder; j<4; j++)
+//                                     file.put((char)0);       // pad it!
+//                             WriteFile(file, padding, 4 - remainder, &bytesWritten, NULL);
+                               fwrite(padding, 1, 4 - remainder, file);
+               }
+       }
+
+       fclose(file);
+
+       return true;                                                            // Whether or not it was successful...
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: BOOL EncodeGlyph(int glyphnum)
+//
+// This function encodes the glyph data and stores it to the 'glyf' table.
+/////////////////////////////////////////////////////////////////////////////
+bool TTF::EncodeGlyph(uint16 glyphnum)
+{
+       bool retval = false;                                            // Assume failure
+       uint8 flag, xbuf[4000], ybuf[4000], fbuf[2000];
+       uint32 xp = 0, yp = 0, fp = 0;                          // Table pointers
+
+       if (glyphnum < myMaxp.numGlyphs)  // numofgls is 1 based ind, glyph# 0 based
+       {
+               // need to add composite encoding...
+               int lastx = 0, lasty = 0;
+
+               for(uint32 i=0; i<numberOfPoints; i++)
+               {
+                       flag = 0;
+                       int curx = gx[i] - lastx, cury = gy[i] - lasty;
+
+                       if (onCurve[i])
+                               flag |= 0x01;                                   // Set on curve info
+
+                       if (curx)
+                       {
+                               if ((curx > 255) || (curx < -255)) // I.e., it's 2 uint8 value
+                                       SetWord(xbuf, xp, curx);
+                               else
+                               {
+                                       if (curx & 0x100)
+                                       {
+                                               flag |= 0x02; // I.e., it's negative
+                                               curx *= -1;   // Flip it so correct value is stored
+                                       }
+                                       else
+                                               flag |= 0x12;
+
+                                       SetByte(xbuf, xp, curx);        // Automagically strips neg bit
+                               }
+                       }
+                       else
+                               flag |= 0x10;                                   // X-coord is same...
+  
+                       if (cury)
+                       {
+                               if ((cury > 255) || (cury < -255)) // I.e., it's 2 uint8 value
+                                       SetWord(ybuf, yp, cury);
+                               else
+                               {
+                                       if (cury & 0x100)
+                                       {
+                                               flag |= 0x04; // I.e., it's negative
+                                               cury *= -1;
+                                       }
+                                       else
+                                               flag |= 0x24;
+            
+                                       SetByte(ybuf, yp, cury);
+                               }
+                       }
+                       else
+                               flag |= 0x20;                 // Y-coord is same...
+  
+                       fbuf[i] = flag;
+                       lastx = gx[i];  lasty = gy[i];
+               }
+
+               // Now crunch flags...  ugly, ugly, ugly.
+/*
+    fbuf[numberOfPoints] = 0;  // Set sentinel value (ugly way to do this)
+    for(i=0; i<numberOfPoints; i++);
+    {
+      if (fbuf[i] == fbuf[i+1])  // 
+      {
+        uint8 count = 0;  // Sentinel takes care of check for end of flags...
+        while (fbuf[i] == fbuf[++i])  count++; // Count number of repeats
+        i--;
+        fbuf[fp++] = fbuf[i] | 0x08; // Set repeat flag
+        fbuf[fp++] = count;          // & number of repeats
+      }
+      else  fbuf[fp++] = fbuf[i];    // Otherwise, just copy...
+    }
+*/
+               fp = numberOfPoints;
+               // Find length of glyph and reallocate space if necessary
+
+               uint32 newLength = 12 + numberOfPolys*2 + numberOfHints + fp + xp + yp;
+
+               if (newLength & 0x03)
+                       newLength += (4 - newLength & 0x03);
+
+               if (glyphLen[glyphnum] != newLength)
+               {
+                       glyph[glyphnum] = (uint8 *)realloc(glyph[glyphnum], newLength);
+                       glyphLen[glyphnum] = newLength;
+               }
+
+               // And finally, store it!
+
+               uint32 gp = 0;                                                  // Glyph pointer...
+               SetWord(glyph[glyphnum], gp, numberOfPolys);
+               SetWord(glyph[glyphnum], gp, llx);
+               SetWord(glyph[glyphnum], gp, lly);
+               SetWord(glyph[glyphnum], gp, urx);
+               SetWord(glyph[glyphnum], gp, ury);
+               for(uint32 i=0; i<numberOfPolys; i++)
+                       SetWord(glyph[glyphnum], gp, poly[i]);
+               SetWord(glyph[glyphnum], gp, numberOfHints);
+               for(uint32 i=0; i<numberOfHints; i++)
+                       SetByte(glyph[glyphnum], gp, hint[i]);
+               for(uint32 i=0; i<fp; i++)
+                       SetByte(glyph[glyphnum], gp, fbuf[i]);
+               for(uint32 i=0; i<xp; i++)
+                       SetByte(glyph[glyphnum], gp, xbuf[i]);
+               for(uint32 i=0; i<yp; i++)
+                       SetByte(glyph[glyphnum], gp, ybuf[i]);
+
+               retval = true;                                                  // Successfully encoded!
+       }
+
+       return retval;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: BOOL DecodeGlyph(int glyphnum)
+//
+// This function decodes the glyph data and stores it to the object's
+// internal array.
+/////////////////////////////////////////////////////////////////////////////
+bool TTF::DecodeGlyph(uint16 glyphnum)
+{
+       bool retval = false;
+       uint32 i, dp;
+
+       // glyphnum is 0 based index, while numGlyphs is 1 based
+       if (glyphnum >= myMaxp.numGlyphs)
+               return false;  // Invalid char #
+
+       if (!glyphLen[glyphnum])
+       {
+               numberOfPoints = numberOfPolys = 0;
+               return true;                                                    // Zero length IS valid...
+       }
+//     else                                                                            // Get character data...
+//     {
+    // Now get the character data...
+       dp = 0;                     // Reset data pointer
+       isCompositeGlyph = false;   // Default is no
+       numberOfPolys = GetWord(glyph[glyphnum], dp);  // # of polygons
+
+       llx = (int16)GetWord(glyph[glyphnum], dp);           // Lower left X
+       lly = (int16)GetWord(glyph[glyphnum], dp);           // Lower left Y
+       urx = (int16)GetWord(glyph[glyphnum], dp);           // Upper right X
+       ury = (int16)GetWord(glyph[glyphnum], dp);           // Upper right Y
+
+       // Need to handle composite glyphs better here.  The ways things
+       // are set now is a recipe for disaster...
+
+       if (numberOfPolys == 0xFFFF)
+       {
+               isCompositeGlyph = true;
+               numberOfPolys = 0;                                              // Set for no points
+
+               Composite cmpst;
+
+               while (!compositeList.IsEmpty())                // Empty composite list...
+                       compositeList.GetFront();
+
+               do
+               {
+                       cmpst.flags = GetWord(glyph[glyphnum], dp);
+                       cmpst.glyphIndex = GetWord(glyph[glyphnum], dp);
+                       cmpst.arg1 = (cmpst.flags & 0x01 ? (int16)GetWord(glyph[glyphnum], dp) : (int8)GetByte(glyph[glyphnum], dp));
+                       cmpst.arg2 = (cmpst.flags & 0x01 ? (int16)GetWord(glyph[glyphnum], dp) : (int8)GetByte(glyph[glyphnum], dp));
+
+                       if (cmpst.flags & 0x08)
+                               cmpst.xScale = cmpst.yScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp));
+                       else if (cmpst.flags & 0x40)
+                               cmpst.xScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)),
+                               cmpst.yScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp));
+                       else if (cmpst.flags & 0x80)
+                               cmpst.xScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)),
+                               cmpst.scale01 = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)),
+                               cmpst.scale10 = FixedToFloat((int16)GetWord(glyph[glyphnum], dp)),
+                               cmpst.yScale = FixedToFloat((int16)GetWord(glyph[glyphnum], dp));
+
+                       compositeList.AddAtRear(cmpst);
+               }
+               while (cmpst.flags & 0x20); //*/
+
+               return true;
+       }
+
+//do {
+//     USHORT flags;
+//     USHORT glyphIndex;
+//     if ( flags & ARG_1_AND_2_ARE_uint16S) {
+//     (SHORT or Fuint16) argument1;
+//     (SHORT or Fuint16) argument2;
+//     } else {
+//             USHORT arg1and2; /* (arg1 << 8) | arg2 */
+//     }
+//     if ( flags & WE_HAVE_A_SCALE ) {
+//             F2Dot14  scale;    /* Format 2.14 */
+//     } else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE ) {
+//             F2Dot14  xscale;    /* Format 2.14 */
+//             F2Dot14  yscale;    /* Format 2.14 */
+//     } else if ( flags & WE_HAVE_A_TWO_BY_TWO ) {
+//             F2Dot14  xscale;    /* Format 2.14 */
+//             F2Dot14  scale01;   /* Format 2.14 */
+//             F2Dot14  scale10;   /* Format 2.14 */
+//             F2Dot14  yscale;    /* Format 2.14 */
+//     }
+//} while ( flags & MORE_COMPONENTS ) 
+//if (flags & WE_HAVE_INSTR){
+//     USHORT numInstr
+//     uint8 instr[numInstr]
+//
+//Flags                    Bit     Description 
+//ARG_1_AND_2_ARE_uint16S    0       If this is set, the arguments are uint16s;
+//                                 otherwise, they are uint8s.
+//ARGS_ARE_XY_VALUES       1       If this is set, the arguments are xy values;
+//                                 otherwise, they are points.
+//ROUND_XY_TO_GRID         2       For the xy values if the preceding is true.
+//WE_HAVE_A_SCALE          3       This indicates that there is a simple scale
+//                                 for the component. Otherwise, scale = 1.0.
+//RESERVED                 4       This bit is reserved.  Set it to 0. 
+//MORE_COMPONENTS          5       Indicates at least one more glyph after this
+//                                 one.
+//WE_HAVE_AN_X_AND_Y_SCALE 6       The x direction will use a different scale
+//                                 from the y direction.
+//WE_HAVE_A_TWO_BY_TWO     7       There is a 2 by 2 transformation that will
+//                                 be used to scale the component.
+//WE_HAVE_INSTRUCTIONS     8       Following the last component are
+//                                 instructions for the composite character.
+//USE_MY_METRICS           9       If set, this forces the aw and lsb (and rsb)
+//                                 for the composite to be equal to those from
+//                                 this original glyph. This works for hinted
+//                                 and unhinted characters.
+
+       for(i=0; i<numberOfPolys; i++)
+               poly[i] = GetWord(glyph[glyphnum], dp);
+
+       numberOfHints = GetWord(glyph[glyphnum], dp);
+
+       for(i=0; i<numberOfHints; i++)
+               hint[i] = GetByte(glyph[glyphnum], dp);
+
+       // Decode the dots...
+
+       uint32 num_pts = poly[numberOfPolys-1] + 1;
+       numberOfPoints = num_pts; // necessary??
+       uint32 xptr, yptr;        // pointers to beginning of coord data
+       uint32 numXs = 0;
+       int xx = 0, yy = 0, repeat;
+       uint32 numTokens = num_pts, k, numRep;
+
+       // We make an educated guess that num_pts = num_tokens; but if there
+       // is repeated data in the tokens, then we need to adjust the # of
+       // tokens down appropriately.
+
+       for(uint32 i=0; i<numTokens; i++)
+       {
+               uint8 token = glyph[glyphnum][dp+i];  uint32 rpts = 1;
+
+               if (token & 0x08)      // Repeated token?
+               {
+                       i++;                 // Yes, bump pointer to # of times to repeat
+                       numRep = glyph[glyphnum][dp+i];
+                       rpts += numRep;
+
+                       if (numRep > 1)      // Do we need to adjust numTokens?
+   // this is bad, modifying numTokens while it's used as a compare value
+   // in the above loop...
+   // Is it necessary to do so in order to keep from going too far?
+                       numTokens -= (numRep - 1); // Yes, adjust.
+               }
+
+               // 10 = same x(0uint8s), 00 = 2uint8s, 02&12 = 1uint8
+               if ((token & 0x02) == 0x02)
+                       numXs += rpts;
+
+               if ((token & 0x12) == 0x00)
+                       numXs += (rpts*2);
+       }
+
+       xptr = dp + numTokens;
+       yptr = dp + numTokens + numXs;
+
+       // & continue decoding X/Y-coords...
+
+       k = 0;                               // Index to the point array
+
+       for(uint32 i=0; i<numTokens; i++)
+       {
+               uint8 token = glyph[glyphnum][dp+i];
+               repeat = 1;
+
+               if (token & 0x08)
+               {
+                       i++;
+                       repeat += glyph[glyphnum][dp+i]; // Set repeat data...
+               }
+
+               while (repeat--)
+               {
+                       if ((token & 0x12) == 0x12)
+                               xx += GetByte(glyph[glyphnum], xptr);
+
+                       if ((token & 0x12) == 0x02)
+                               xx -= GetByte(glyph[glyphnum], xptr);
+
+                       if ((token & 0x12) == 0x00)
+                               xx += (int16)GetWord(glyph[glyphnum], xptr);
+
+                       gx[k] = xx;                      // Store x-coordinate
+
+                       if ((token & 0x24) == 0x24)
+                               yy += GetByte(glyph[glyphnum], yptr);
+
+                       if ((token & 0x24) == 0x04)
+                               yy -= GetByte(glyph[glyphnum], yptr);
+
+                       if ((token & 0x24) == 0x00)
+                               yy += (int16)GetWord(glyph[glyphnum], yptr);
+
+                       gy[k] = yy;                      // Store y-coordinate
+
+                       onCurve[k++] = (token & 0x01 ? true : false);  // If bit 0 set, then it's on curve
+               }
+       }
+
+       retval = true;                                                  // Hmm. Successfully decoded a glyph...
+//     }
+
+       isDirty = false;  // do it here?
+
+       return retval;
+}
+
+/*****************************************************************************
+ Member function:
+
+ This function decodes the 'glyf' data for a non-composite (atomic) glyph and
+ returns it as a GlyphPoints object. Helper function.
+ *****************************************************************************/
+GlyphPoints TTF::GetGlyphPoints(uint16 glyphNum)
+{
+       if (DecodeGlyph(glyphNum))
+               return GlyphPoints(numberOfPoints, numberOfPolys, gx, gy, onCurve, poly);
+
+       return GlyphPoints();
+}
+
+/*****************************************************************************
+ Member function:
+
+ This function decodes the 'glyf' data for a composite glyph and returns
+ it as a GlyphPoints object.
+ *****************************************************************************/
+GlyphPoints TTF::GetAllCompositePoints(uint16 glyphNum)
+{
+//  int tmpGlyph = currentGlyph;
+  
+       DecodeGlyph(glyphNum);         // Check for composite-ness
+
+       if (!isCompositeGlyph)
+               return GlyphPoints();
+
+/*
+  for(int i=1; i<=pDoc->m_myFont.compositeList.Length(); i++)
+  {
+    TComposite cmpst = fnt->compositeList.PeekPosition(i);
+    fnt->SetGlyph(cmpst.glyphIndex);
+    if (cmpst.flags & 0x0002)
+      m_nXOffset = cmpst.arg1, m_nYOffset = cmpst.arg2;
+    ScanConvertSingleGlyph(pDC, nScanlines, nHorzLines, nXOffset, nYOffset);
+  }
+  fnt->SetGlyph(pDoc->character_num);
+*/
+
+       GlyphPoints retVal;
+
+       for(int i=1; i<=compositeList.Length(); i++)
+       {
+               Composite cmpst = compositeList.PeekPosition(i);
+    
+//    SetGlyph(cmpst.glyphIndex);
+//    if (cmpst.flags & 0x0002)
+//      m_nXOffset = cmpst.arg1, m_nYOffset = cmpst.arg2;
+//    ScanConvertSingleGlyph(pDC, nScanlines, nHorzLines, nXOffset, nYOffset);
+               GlyphPoints gp = GetGlyphPoints(cmpst.glyphIndex);
+
+               if (cmpst.flags & 0x0002)
+                       gp.OffsetPoints(cmpst.arg1, cmpst.arg2);
+
+               retVal = retVal + gp;
+               // NOTE: May have to adjust scanlines as per 0x0002 above...
+       }
+
+//  SetGlyph(tmpGlyph);
+       DecodeGlyph(currentGlyph);     // Reset needed here...
+
+       return retVal;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: void GetCharName(int cNum, uint8 * buf)
+//
+// This function returns the character name of the glyph number passed in.
+/////////////////////////////////////////////////////////////////////////////
+void TTF::GetCharName(int cNum, uint8 * buf)
+{
+       buf[0] = 0;                                                                     // Set failure as default condition
+  
+       if (!post)                                                                      // PS names are here...
+               return;
+
+       if (post[1] != 0x02 || post[2] != 0x00)         // i.e., it's NOT a V2.0 table
+               return;
+
+       uint8 * pTab = NULL;
+       uint32 tabOff = 34, numGlyphs = (uint32)((post[32] << 8) | post[33]);
+       uint32 index = (uint32)((post[tabOff + cNum * 2] << 8) | post[tabOff + cNum * 2 + 1]);
+       uint32 nInd2;
+
+       if (index > 257)
+       {
+               index -= 258;
+               nInd2 = tabOff + (2 * numGlyphs);
+               pTab = post;
+       }
+       else
+       {
+               nInd2 = 0;
+               pTab = macStdNames;
+       }
+
+       for(uint32 i=0; i<index; i++)
+               nInd2 = nInd2 + pTab[nInd2] + 1; // 1st uint8 is length of string + that uint8
+
+       uint8 len = pTab[nInd2];
+       nInd2++;
+
+       for(uint8 i=0; i<len; i++)
+               buf[i] = pTab[nInd2 + i];
+
+       buf[len] = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: BOOL ExtractTables(void)
+//
+// This function extracts the data from the various tables and puts them in
+// various structs for easier handling of the font data.
+/////////////////////////////////////////////////////////////////////////////
+bool TTF::ExtractTables(void)
+{
+       if (head_len != 54)
+       {
+#ifdef TTFDEBUG
+WriteLogMsg("Bad HEAD header: Expected 54, found %u...\n", head_len);
+#endif
+               return false;                                                   // Corrupt data?
+       }
+
+       uint32 tp = 0;
+       myHead.version            = GetDWord(head, tp);
+       myHead.fontRevision       = GetDWord(head, tp);
+       myHead.checkSumAdjustment = GetDWord(head, tp);
+       myHead.magicNumber        = GetDWord(head, tp);
+       myHead.flags              = GetWord(head, tp);
+       myHead.unitsPerEm         = GetWord(head, tp);
+       myHead.createdh           = GetDWord(head, tp);
+       myHead.createdl           = GetDWord(head, tp);
+       myHead.modifiedh          = GetDWord(head, tp);
+       myHead.modifiedl          = GetDWord(head, tp);
+       myHead.xMin               = GetWord(head, tp);
+       myHead.yMin               = GetWord(head, tp);
+       myHead.xMax               = GetWord(head, tp);
+       myHead.yMax               = GetWord(head, tp);
+       myHead.macStyle           = GetWord(head, tp);
+       myHead.lowestRecPPEM      = GetWord(head, tp);
+       myHead.fontDirectionHint  = (int16)GetWord(head, tp);
+       myHead.indexToLocFormat   = (int16)GetWord(head, tp);
+       myHead.glyphDataFormat    = (int16)GetWord(head, tp);
+
+       if (maxp_len != 32)
+       {
+#ifdef TDEBUG
+WriteLogMsg("Bad MAXP header: Expected 32, found %u...\n", maxp_len);
+#endif
+               return false;                                                   // Corrupt data?
+       }
+
+       tp = 0;                                                                         // Reset table pointer
+       myMaxp.version               = GetDWord(maxp, tp);
+       myMaxp.numGlyphs             = GetWord(maxp, tp);
+       myMaxp.maxPoints             = GetWord(maxp, tp);
+       myMaxp.maxContours           = GetWord(maxp, tp);
+       myMaxp.maxCompositePoints    = GetWord(maxp, tp);
+       myMaxp.maxCompositeContours  = GetWord(maxp, tp);
+       myMaxp.maxZones              = GetWord(maxp, tp);
+       myMaxp.maxTwilightPoints     = GetWord(maxp, tp);
+       myMaxp.maxStorage            = GetWord(maxp, tp);
+       myMaxp.maxFunctionDefs       = GetWord(maxp, tp);
+       myMaxp.maxInstructionDefs    = GetWord(maxp, tp);
+       myMaxp.maxStackElements      = GetWord(maxp, tp);
+       myMaxp.maxSizeOfInstructions = GetWord(maxp, tp);
+       myMaxp.maxComponentElements  = GetWord(maxp, tp);
+       myMaxp.maxComponentDepth     = GetWord(maxp, tp);
+
+       tp = 0;                                                                         // Reset table pointer
+       uint32 start = (myHead.indexToLocFormat ? GetDWord(loca, tp) : GetWord(loca, tp) << 1);
+
+       for(uint32 i=0; i<myMaxp.numGlyphs; i++)
+       {
+               uint32 end = (myHead.indexToLocFormat ? GetDWord(loca, tp) : GetWord(loca, tp) << 1);
+               uint32 length = end - start;
+               glyphLen[i] = length;                                   // Lengths are saved 'cause malloc is sloppy
+
+               if (length)     // loca+start? pointer arithmetic?
+               {
+                       glyph[i] = (uint8 *)malloc(length);     // Allocate space,
+                       memcpy(glyph[i], glyf+start, length);   // and move it!
+               }
+               else
+                       glyph[i] = NULL;
+
+               start = end;                                                    // Reset start value
+       }
+
+       return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: BOOL BuildTables(void)
+//
+// This function builds the various TTF tables using info in the various
+// structs so that a TTF file can be written out to disk.
+/////////////////////////////////////////////////////////////////////////////
+bool TTF::BuildTables(void)
+{
+       uint32 i, tp, start;
+
+       myHead.indexToLocFormat = 1;                            // We don't bother with [uint16s*2] format...
+
+       // Build HEAD table
+
+       tp = 0;                                                                         // Reset table pointer
+       SetDWord(head, tp, myHead.version);//            = GetDWord(head, tp);
+       SetDWord(head, tp, myHead.fontRevision);//       = GetDWord(head, tp);
+       SetDWord(head, tp, myHead.checkSumAdjustment);// = GetDWord(head, tp);
+       SetDWord(head, tp, myHead.magicNumber);//        = GetDWord(head, tp);
+       SetWord(head, tp, myHead.flags);//              = GetWord(head, tp);
+       SetWord(head, tp, myHead.unitsPerEm);//         = GetWord(head, tp);
+       SetDWord(head, tp, myHead.createdh);//           = GetDWord(head, tp);
+       SetDWord(head, tp, myHead.createdl);//           = GetDWord(head, tp);
+       SetDWord(head, tp, myHead.modifiedh);//          = GetDWord(head, tp);
+       SetDWord(head, tp, myHead.modifiedl);//          = GetDWord(head, tp);
+       SetWord(head, tp, myHead.xMin);//               = GetWord(head, tp);
+       SetWord(head, tp, myHead.yMin);//               = GetWord(head, tp);
+       SetWord(head, tp, myHead.xMax);//               = GetWord(head, tp);
+       SetWord(head, tp, myHead.yMax);//               = GetWord(head, tp);
+       SetWord(head, tp, myHead.macStyle);//           = GetWord(head, tp);
+       SetWord(head, tp, myHead.lowestRecPPEM);//      = GetWord(head, tp);
+       SetWord(head, tp, myHead.fontDirectionHint);//  = (int16)GetWord(head, tp);
+       SetWord(head, tp, myHead.indexToLocFormat);//   = (int16)GetWord(head, tp);
+       SetWord(head, tp, myHead.glyphDataFormat);//    = (int16)GetWord(head, tp);
+
+       // Build MAXP table
+
+       tp = 0;                                                                         // Reset table pointer
+       SetDWord(maxp, tp, myMaxp.version);//               = GetDWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.numGlyphs);//             = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxPoints);//             = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxContours);//           = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxCompositePoints);//    = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxCompositeContours);//  = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxZones);//              = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxTwilightPoints);//     = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxStorage);//            = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxFunctionDefs);//       = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxInstructionDefs);//    = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxStackElements);//      = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxSizeOfInstructions);// = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxComponentElements);//  = GetWord(maxp, tp);
+       SetWord(maxp, tp, myMaxp.maxComponentDepth);//     = GetWord(maxp, tp);
+
+       // Build LOCA & GLYF tables
+
+       loca_len = (myMaxp.numGlyphs+1) * 4;            // Set size of table
+
+       if (loca)
+               free(loca);                                                             // And create/reallocate it...
+
+       loca = (uint8 *) malloc(loca_len);
+
+       glyf_len = 0;                                                           // Refigure glyf table length
+
+       for(i=0; i<myMaxp.numGlyphs; i++)
+               glyf_len += glyphLen[i];
+
+       if (glyf)
+               free(glyf);
+
+       glyf = (uint8 *) malloc(glyf_len);
+
+       start = tp = 0;                                                         // Reset table pointer
+
+       for(i=0; i<myMaxp.numGlyphs; i++)
+       {
+               SetDWord(loca, tp, start);                              // Store glyph start address
+
+               if (glyphLen[i])
+                       memcpy(glyf+start, glyph[i], glyphLen[i]);
+
+               start += glyphLen[i];
+       }
+
+       SetDWord(loca, tp, start);                                      // Finally, store end of glyphs+1
+
+       return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: BOOL SetGlyph(int glyphnum)
+//
+// This function decodes the glyph data and stores the points in its own
+// internal array.  If the flag isDirty is set, it also encodes the internal
+// array and stores it to the 'glyf' table.
+/////////////////////////////////////////////////////////////////////////////
+bool TTF::SetGlyph(uint16 glyphnum)
+{
+       bool retval = false;                                            // Set failure as default
+
+       if (isDirty)
+               EncodeGlyph(currentGlyph);
+
+       isDirty = false;
+
+       if (glyphnum < myMaxp.numGlyphs)                        // numofgls is 1 based ind, glyph# 0 based
+       {
+               currentGlyph = glyphnum;
+               DecodeGlyph(currentGlyph);
+               retval = true;
+       }
+
+       return retval;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: BOOL AddGlyph(int glyphnum)
+//
+// This function adds a glyph of zero size at position glyphnum.  If glyphnum
+// is greater than the number of glyphs, glyph is added at end of list. This
+// glyph then becomes the current glyph.
+/////////////////////////////////////////////////////////////////////////////
+bool TTF::AddGlyph(uint16 glyphnum)
+{
+       // incomplete: JLH
+       bool retval = false;
+
+       if (isDirty)
+               EncodeGlyph(currentGlyph);
+
+       isDirty = false;
+
+       return retval;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Member function: BOOL DeleteGlyph(int glyphnum)
+//
+// This function deletes the glyph at position glyphnum.  All glyphs after
+// this glyph are moved down in position.
+/////////////////////////////////////////////////////////////////////////////
+bool TTF::DeleteGlyph(uint16 glyphnum)
+{
+       // incomplete: JLH
+       bool retval = false;
+
+       return retval;
+}
+
+//
+// Various & sundry member functions implementation
+//
+// NOTE: For error handling, should throw exceptions--not return values...! !!! FIX !!!
+//
+
+Box TTF::GetBoundingBox(void)
+{
+       return Box(llx, lly, urx, ury);
+}
+
+GlyphPt TTF::GetPoint(uint16 pointno)
+{
+       GlyphPt p;
+
+       if (pointno >= MAXPOINTS)
+               return p; // Fix to make invalid
+
+       p.x = gx[pointno], p.y = gy[pointno], p.onCurve = onCurve[pointno];
+       return p;
+}
+
+uint16 TTF::GetNumberOfPolys(void)
+{
+       return numberOfPolys;
+}
+
+uint16 TTF::GetPolyEnd(uint16 polynum)
+{
+       if (polynum >= numberOfPolys)
+               return 0;
+
+       return poly[polynum];
+}
+
+int TTF::GetPointX(uint16 pointno)
+{
+       if (pointno >= MAXPOINTS)
+               return 0;
+
+       return gx[pointno];
+}
+
+int TTF::GetPointY(uint16 pointno)
+{
+       if (pointno >= MAXPOINTS)
+               return 0;
+
+       return gy[pointno];
+}
+
+bool TTF::GetOnCurve(uint16 pointno)
+{
+       if (pointno >= MAXPOINTS)
+               return true;
+
+       return onCurve[pointno];
+}
+
+bool TTF::SetOnCurve(uint16 pointno, bool state)
+{
+       if (pointno >= numberOfPoints)
+               return false;
+
+       onCurve[pointno] = state;
+       isDirty = true;
+
+       return true;
+}
+
+bool TTF::MovePoint(uint16 pointno, int x, int y)
+{
+       if (pointno >= numberOfPoints)
+               return false;
+
+       gx[pointno] = x;  gy[pointno] = y;
+       isDirty = true;
+
+       return true;
+}
+
+bool TTF::MovePoint(uint16 pointno, GlyphPt p)
+{
+       if (pointno >= numberOfPoints)
+               return false;
+
+       gx[pointno] = p.x;  gy[pointno] = p.y;  onCurve[pointno] = p.onCurve;
+       isDirty = true;
+
+       return true;
+}
+
+bool TTF::IsCompositeGlyph(void)
+{
+       return isCompositeGlyph;
+}
+
index 07aac36a044eff6397e9a04c2fec3aed38d0e4e8..2ea45be926f220cc29ced99bd2c378f38cc02189 100755 (executable)
--- a/src/ttf.h
+++ b/src/ttf.h
-//\r
-// TTF.H: TTF Class\r
-// by James L. Hammons\r
-// (C) 1999 Underground Software\r
-//\r
-// This class encapsulates all the complexity of a TrueType Font File\r
-// database.  Included are functions to load, save, & initialize the\r
-// TTF database.\r
-//\r
-\r
-// These really shouldn't be included here, but are for now...\r
-//#include <string.h>\r
-////#include <afxwin.h>  // This is needed only for things like BOOL, etc.\r
-//#include <fstream.h>\r
-//#include <stdlib.h>\r
-//#include <malloc.h>  // Both for malloc, free, _msize, realloc\r
-\r
-#ifndef __TTF_H__\r
-#define __TTF_H__\r
-\r
-#include "list.h"\r
-#include "types.h"\r
-#include "glyphpoints.h"\r
-\r
-#define MAXGLYPHS 4096                 // Number of glyphs in object\r
-#define MAXPOINTS 2000                 // Number of points in a glyph\r
-#define MAXHINTS  2000                 // Number of hint uint8s in glyph\r
-\r
-//\r
-// "head" struct\r
-//\r
-struct Head\r
-{\r
-       uint32 version;                         // Fixed - Table version number (0x00010000 for version 1.0.)\r
-       uint32 fontRevision;            // Fixed - fontRevision (Set by font manufacturer.)\r
-       uint32 checkSumAdjustment;      // To compute: Set it to 0, sum the entire font\r
-                                                               // as ULONG, then store 0xB1B0AFBA - sum.\r
-       uint32 magicNumber;                     // Set to 0x5F0F3CF5.\r
-       uint16 flags;                           /* Bit 0 - baseline for font at y=0;\r
-                                                                  Bit 1 - left sidebearing at x=0;\r
-                                                                  Bit 2 - instructions may depend on point     size;\r
-                                                                  Bit 3 - force ppem to integer values for all\r
-                                                                                       internal scaler math; may use\r
-                                                                                       fractional ppem sizes if this bit is clear;\r
-                                                                  Bit 4 - instructions may alter advance width\r
-                                                                                       (the advance widths might not scale linearly);\r
-                                                                  Note: All other bits must be zero.*/\r
-       uint16 unitsPerEm;                      // Valid range is from 16 to 16384\r
-       uint32 /*longDateTime*/ createdh, createdl;             // International date (8-uint8 field).\r
-       uint32 /*longDateTime*/ modifiedh, modifiedl;   // International date (8-uint8 field).\r
-       uint16 xMin;                            // For all glyph bounding boxes.\r
-       uint16 yMin;                            // For all glyph bounding boxes.\r
-       uint16 xMax;                            // For all glyph bounding boxes.\r
-       uint16 yMax;                            // For all glyph bounding boxes.\r
-       uint16 macStyle;                        /* Bit 0 bold (if set to 1); Bit 1 italic (if set to 1)\r
-                                                                  Bits 2-15 reserved (set to 0).*/\r
-       uint16 lowestRecPPEM;           // Smallest readable size in pixels.\r
-       int16  fontDirectionHint;       /* 0   Fully mixed directional glyphs;\r
-                                                                  1   Only strongly left to right;\r
-                                                                  2   Like 1 but also contains neutrals;\r
-                                                                 -1   Only strongly right to left;\r
-                                                                 -2   Like -1 but also contains neutrals.*/\r
-       int16  indexToLocFormat;        // 0 for short offsets, 1 for long.\r
-       int16  glyphDataFormat;         // 0 for current format.\r
-};\r
-\r
-//\r
-// "maxp" struct\r
-//\r
-struct Maxp\r
-{\r
-       uint32 version;                                 // Table version number 0x00010000 for version 1.0. \r
-       uint16 numGlyphs;                               // The number of glyphs in the font. \r
-       uint16 maxPoints;                               // Maximum points in a non-composite glyph. \r
-       uint16 maxContours;                             // Maximum contours in a non-composite glyph. \r
-       uint16 maxCompositePoints;              // Maximum points in a composite glyph. \r
-       uint16 maxCompositeContours;    // Maximum contours in a composite glyph. \r
-       uint16 maxZones;                                // 1 if instructions do not use the twilight\r
-                                                                       // zone (Z0), or 2 if instructions do use Z0;\r
-                                                                       // should be set to 2 in most cases. \r
-       uint16 maxTwilightPoints;               // Maximum points used in Z0. \r
-       uint16 maxStorage;                              // Number of Storage Area locations.  \r
-       uint16 maxFunctionDefs;                 // Number of FDEFs. \r
-       uint16 maxInstructionDefs;              // Number of IDEFs. \r
-       uint16 maxStackElements;                // Maximum stack depth. \r
-       uint16 maxSizeOfInstructions;   // Maximum uint8 count for glyph instructions. \r
-       uint16 maxComponentElements;    // Maximum number of components referenced at\r
-                                                                       // "top level" for any composite glyph. \r
-       uint16 maxComponentDepth;               // Maximum levels of recursion; 1 for simple components.\r
-};\r
-\r
-//\r
-// "cmap" struct\r
-//\r
-/*\r
-USHORT Table version number (0).\r
-USHORT Number of encoding tables, n.   \r
-\r
-This is followed by an entry for each of the n encoding table specifying the\r
-particular encoding, and the offset to the actual subtable:\r
-\r
-Type   Description     \r
-USHORT Platform ID.    \r
-USHORT Platform-specific encoding ID.  \r
-ULONG  uint8 offset from beginning of table to the subtable for this encoding. \r
-\r
-USHORT  format          Format number is set to 4.  \r
-USHORT  length          Length in uint8s.  \r
-USHORT version Version number (starts at 0).   \r
-USHORT segCountX2      2 x segCount.   \r
-USHORT searchRange     2 x (2**floor(log2(segCount)))  \r
-USHORT entrySelector   log2(searchRange/2)     \r
-USHORT rangeShift      2 x segCount - searchRange      \r
-USHORT endCount[segCount]      End characterCode for each segment,\r
-                        last =0xFFFF. \r
-USHORT reservedPad     Set to 0.       \r
-USHORT startCount[segCount]    Start character code for each segment.  \r
-USHORT idDelta[segCount]       Delta for all character codes in segment.       \r
-USHORT idRangeOffset[segCount] Offsets into glyphIdArray or 0  \r
-USHORT glyphIdArray[ ] Glyph index array (arbitrary length)    \r
-\r
-The number of segments is specified by segCount, which is not explicitly in\r
-the header; however, all of the header parameters are derived from it. The\r
-searchRange value is twice the largest power of 2 that is less than or equal\r
-to  segCount. For example, if segCount=39, we have the following:\r
-\r
-segCountX2     78\r
-searchRange     64      (2 * largest power of 2 <= 39)\r
-entrySelector  5       log2(32)\r
-rangeShift     14      2 x 39 - 64\r
-*/\r
-\r
-struct GlyphPt\r
-{\r
-       int x, y;\r
-       bool onCurve;\r
-\r
-       // Default constructor\r
-       GlyphPt(int xx = 0, int yy = 0, bool oc = true): x(xx), y(yy), onCurve(oc) {}\r
-};\r
-\r
-struct Box\r
-{\r
-       int16 llx, lly, urx, ury;\r
-\r
-       // Default constructor\r
-       Box(int16 lx = 0, int16 ly = 0, int16 rx = 0, int16 ry = 0):\r
-               llx(lx), lly(ly), urx(rx), ury(ry) {}\r
-};\r
-\r
-struct NameRec\r
-{\r
-       uint16 platformID, platformSpecID, languageID, nameID, length;\r
-       uint8 * str;\r
-\r
-       NameRec(): str(NULL) {}\r
-\r
-       NameRec(NameRec &c): str(NULL)\r
-       {\r
-               *this = c;\r
-       }\r
-\r
-       ~NameRec()\r
-       {\r
-               if (str)\r
-                       delete[] str;\r
-       }\r
-\r
-       void operator=(const NameRec &c)\r
-       {\r
-               if (this == &c)\r
-                       return;                                                         // Take care of self-assignment\r
-\r
-               if (str)\r
-                       delete[] str;\r
-\r
-               platformID     = c.platformID;\r
-               platformSpecID = c.platformSpecID;\r
-               languageID     = c.languageID;\r
-               nameID         = c.nameID;\r
-               length         = c.length;\r
-//Fix this             str            = (uint8 *)strdup((char *)c.str);\r
-       }\r
-};\r
-\r
-struct Composite\r
-{\r
-       uint16 flags, glyphIndex;\r
-       int16 arg1, arg2;\r
-       float xScale, yScale, scale01, scale10;\r
-\r
-       Composite(uint16 fl = 0, uint16 gl = 0, int16 a1 = 0, int16 a2 = 0,\r
-               float xs = 1.0f, float ys = 1.0f, float s01 = 1.0f, float s10 = 1.0f):\r
-               flags(fl), glyphIndex(gl), arg1(a1), arg2(a2), xScale(xs), yScale(ys),\r
-               scale01(s01), scale10(s10) {}\r
-};\r
-\r
-//\r
-// The TTF class\r
-//\r
-// The following is a set of member functions that needs to be implemented\r
-// to fully encapsulate a TTF database.\r
-//\r
-// SetGlyph(glyphno)\r
-// DeleteGlyph(glyphno)\r
-// AddGlyph()\r
-// GetNumberOfPolys()\r
-// GetPolyStart(polyno)\r
-// SetPolyStart(polyno)\r
-// AddPoly(polyno)\r
-// DeletePoly(polyno)\r
-// IsCompositeGlyph()\r
-// MovePoint(pointno, x, y)\r
-// AddPoint(pointno, x, y)\r
-// DeletePoint(pointno)\r
-// maybe:  TGlyphPt GetPointInfo(pointno) instead of three following...\r
-// GetPointX(pointno)\r
-// GetPointY(pointno)\r
-// GetOnCurve(pointno)\r
-// SetOnCurve(pointno)\r
-// ConnectGlyphToChar(glyphno, charno)\r
-// EncodeGlyph(glyphno)\r
-// DecodeGlyph(glyphno)\r
-// GetNumberOfPoints()\r
-// SwapPoints(pointno1, pointno2)\r
-//\r
-// More to be added, as necessary...\r
-//\r
-class TTF\r
-{\r
-       private:\r
-               bool EncodeGlyph(uint16);\r
-               bool DecodeGlyph(uint16);\r
-               bool ExtractTables(void);\r
-               bool BuildTables(void);\r
-\r
-       public:\r
-               TTF(void);                                                              // Constructor\r
-               ~TTF();                                                                 // Destructor\r
-               void Init(void);                                                // Initalize font database\r
-               bool Load(const char *);                                // Load font database\r
-               bool Save(const char *);                                // Save font database\r
-               void ClearTables(void);                                 // Deallocate memory...\r
-               bool SetGlyph(uint16 glyphnum);                 // Set internal pointer/encode/decode\r
-               bool AddGlyph(uint16 glyphnum);\r
-               bool DeleteGlyph(uint16 glyphnum);\r
-               Box GetBoundingBox(void);\r
-               GlyphPt GetPoint(uint16 pointno);\r
-               uint16 GetNumberOfPolys(void);\r
-               uint16 GetPolyEnd(uint16 polynum);\r
-               int GetPointX(uint16 pointno);\r
-               int GetPointY(uint16 pointno);\r
-               bool GetOnCurve(uint16 pointno);\r
-               bool SetOnCurve(uint16 pointno, bool state);\r
-               bool MovePoint(uint16 pointno, int x, int y);\r
-               bool MovePoint(uint16 pointno, GlyphPt p);\r
-               bool AddPoint(uint16 pointno, int x, int y, bool state);\r
-               bool DeletePoint(uint16 pointno);\r
-               bool IsCompositeGlyph(void);\r
-               GlyphPoints GetGlyphPoints(uint16);\r
-               GlyphPoints GetAllCompositePoints(uint16);\r
-               void GetCharName(int, uint8 *);\r
-\r
-       private:\r
-               bool isDirty;                                                   // Has glyph been modified?\r
-               bool isCompositeGlyph;                                  // Is it a composite? (need structs to store composite info...)\r
-               uint16 currentGlyph;                                    // The glyph currently decoded\r
-               uint16 numberOfPoints;\r
-               int gx[MAXPOINTS];                                              // Internal point arrays...\r
-               int gy[MAXPOINTS];                                              // These could be dynamically allocated in the\r
-               bool onCurve[MAXPOINTS];                                // constructor, with default values being set\r
-               uint16 numberOfHints;\r
-               uint8 hint[MAXHINTS];                                   // Hints storage\r
-               uint16 numberOfPolys;                                   // Number of polygons in glyph\r
-               uint16 poly[200];                                               // End points of polygons\r
-               int16 llx, lly, urx, ury;                               // Lower left/Upper right X/Y\r
-//     public://remove after debugging...\r
-               uint8 * glyph[MAXGLYPHS];                               // Placeholders for glyphs\r
-               uint32 glyphLen[MAXGLYPHS];                             // Glyph lengths are stored since malloc() is sloppy\r
-               Maxp myMaxp;                                                    // Internal placeholders for this shiat\r
-               Head myHead;\r
-//     public: //private: later...\r
-               List<Composite> compositeList;                  // Composite glyph list\r
-               uint8 * EBDT, * EBLC, * EBSC, * LTSH, * OS_2, * PCLT, * VDMX, * cmap, * cvt,  * fpgm,\r
-                       * gasp, * glyf, * hdmx, * head, * hhea, * hmtx, * kern, * loca, * maxp, * name,\r
-                       * post, * prep, * vhea, * vmtx;\r
-               uint32 EBDT_len, EBLC_len, EBSC_len, LTSH_len, OS_2_len, PCLT_len, VDMX_len, cmap_len,\r
-                       cvt_len,  fpgm_len, gasp_len, glyf_len, hdmx_len, head_len, hhea_len, hmtx_len,\r
-                       kern_len, loca_len, maxp_len, name_len, post_len, prep_len, vhea_len, vmtx_len;\r
-               uint8 * * parray[24];                                   // Pointer array\r
-               uint32 * larray[24];                                    // Length array\r
-               bool loaded;                                                    // Font loaded/init'ed?\r
-};\r
-\r
-#endif // __TTF_H__\r
-\r
+//
+// TTF.H: TTF Class
+// by James L. Hammons
+// (C) 1999 Underground Software
+//
+// This class encapsulates all the complexity of a TrueType Font File
+// database.  Included are functions to load, save, & initialize the
+// TTF database.
+//
+
+// These really shouldn't be included here, but are for now...
+//#include <string.h>
+////#include <afxwin.h>  // This is needed only for things like BOOL, etc.
+//#include <fstream.h>
+//#include <stdlib.h>
+//#include <malloc.h>  // Both for malloc, free, _msize, realloc
+
+#ifndef __TTF_H__
+#define __TTF_H__
+
+#include "list.h"
+#include "types.h"
+#include "glyphpoints.h"
+
+#define MAXGLYPHS 4096                 // Number of glyphs in object
+#define MAXPOINTS 2000                 // Number of points in a glyph
+#define MAXHINTS  2000                 // Number of hint uint8s in glyph
+
+//
+// "head" struct
+//
+struct Head
+{
+       uint32 version;                         // Fixed - Table version number (0x00010000 for version 1.0.)
+       uint32 fontRevision;            // Fixed - fontRevision (Set by font manufacturer.)
+       uint32 checkSumAdjustment;      // To compute: Set it to 0, sum the entire font
+                                                               // as ULONG, then store 0xB1B0AFBA - sum.
+       uint32 magicNumber;                     // Set to 0x5F0F3CF5.
+       uint16 flags;                           /* Bit 0 - baseline for font at y=0;
+                                                                  Bit 1 - left sidebearing at x=0;
+                                                                  Bit 2 - instructions may depend on point     size;
+                                                                  Bit 3 - force ppem to integer values for all
+                                                                                       internal scaler math; may use
+                                                                                       fractional ppem sizes if this bit is clear;
+                                                                  Bit 4 - instructions may alter advance width
+                                                                                       (the advance widths might not scale linearly);
+                                                                  Note: All other bits must be zero.*/
+       uint16 unitsPerEm;                      // Valid range is from 16 to 16384
+       uint32 /*longDateTime*/ createdh, createdl;             // International date (8-uint8 field).
+       uint32 /*longDateTime*/ modifiedh, modifiedl;   // International date (8-uint8 field).
+       uint16 xMin;                            // For all glyph bounding boxes.
+       uint16 yMin;                            // For all glyph bounding boxes.
+       uint16 xMax;                            // For all glyph bounding boxes.
+       uint16 yMax;                            // For all glyph bounding boxes.
+       uint16 macStyle;                        /* Bit 0 bold (if set to 1); Bit 1 italic (if set to 1)
+                                                                  Bits 2-15 reserved (set to 0).*/
+       uint16 lowestRecPPEM;           // Smallest readable size in pixels.
+       int16  fontDirectionHint;       /* 0   Fully mixed directional glyphs;
+                                                                  1   Only strongly left to right;
+                                                                  2   Like 1 but also contains neutrals;
+                                                                 -1   Only strongly right to left;
+                                                                 -2   Like -1 but also contains neutrals.*/
+       int16  indexToLocFormat;        // 0 for short offsets, 1 for long.
+       int16  glyphDataFormat;         // 0 for current format.
+};
+
+//
+// "maxp" struct
+//
+struct Maxp
+{
+       uint32 version;                                 // Table version number 0x00010000 for version 1.0. 
+       uint16 numGlyphs;                               // The number of glyphs in the font. 
+       uint16 maxPoints;                               // Maximum points in a non-composite glyph. 
+       uint16 maxContours;                             // Maximum contours in a non-composite glyph. 
+       uint16 maxCompositePoints;              // Maximum points in a composite glyph. 
+       uint16 maxCompositeContours;    // Maximum contours in a composite glyph. 
+       uint16 maxZones;                                // 1 if instructions do not use the twilight
+                                                                       // zone (Z0), or 2 if instructions do use Z0;
+                                                                       // should be set to 2 in most cases. 
+       uint16 maxTwilightPoints;               // Maximum points used in Z0. 
+       uint16 maxStorage;                              // Number of Storage Area locations.  
+       uint16 maxFunctionDefs;                 // Number of FDEFs. 
+       uint16 maxInstructionDefs;              // Number of IDEFs. 
+       uint16 maxStackElements;                // Maximum stack depth. 
+       uint16 maxSizeOfInstructions;   // Maximum uint8 count for glyph instructions. 
+       uint16 maxComponentElements;    // Maximum number of components referenced at
+                                                                       // "top level" for any composite glyph. 
+       uint16 maxComponentDepth;               // Maximum levels of recursion; 1 for simple components.
+};
+
+//
+// "cmap" struct
+//
+/*
+USHORT Table version number (0).
+USHORT Number of encoding tables, n.   
+
+This is followed by an entry for each of the n encoding table specifying the
+particular encoding, and the offset to the actual subtable:
+
+Type   Description     
+USHORT Platform ID.    
+USHORT Platform-specific encoding ID.  
+ULONG  uint8 offset from beginning of table to the subtable for this encoding. 
+
+USHORT  format          Format number is set to 4.  
+USHORT  length          Length in uint8s.  
+USHORT version Version number (starts at 0).   
+USHORT segCountX2      2 x segCount.   
+USHORT searchRange     2 x (2**floor(log2(segCount)))  
+USHORT entrySelector   log2(searchRange/2)     
+USHORT rangeShift      2 x segCount - searchRange      
+USHORT endCount[segCount]      End characterCode for each segment,
+                        last =0xFFFF. 
+USHORT reservedPad     Set to 0.       
+USHORT startCount[segCount]    Start character code for each segment.  
+USHORT idDelta[segCount]       Delta for all character codes in segment.       
+USHORT idRangeOffset[segCount] Offsets into glyphIdArray or 0  
+USHORT glyphIdArray[ ] Glyph index array (arbitrary length)    
+
+The number of segments is specified by segCount, which is not explicitly in
+the header; however, all of the header parameters are derived from it. The
+searchRange value is twice the largest power of 2 that is less than or equal
+to  segCount. For example, if segCount=39, we have the following:
+
+segCountX2     78
+searchRange     64      (2 * largest power of 2 <= 39)
+entrySelector  5       log2(32)
+rangeShift     14      2 x 39 - 64
+*/
+
+struct GlyphPt
+{
+       int x, y;
+       bool onCurve;
+
+       // Default constructor
+       GlyphPt(int xx = 0, int yy = 0, bool oc = true): x(xx), y(yy), onCurve(oc) {}
+};
+
+struct Box
+{
+       int16 llx, lly, urx, ury;
+
+       // Default constructor
+       Box(int16 lx = 0, int16 ly = 0, int16 rx = 0, int16 ry = 0):
+               llx(lx), lly(ly), urx(rx), ury(ry) {}
+};
+
+struct NameRec
+{
+       uint16 platformID, platformSpecID, languageID, nameID, length;
+       uint8 * str;
+
+       NameRec(): str(NULL) {}
+
+       NameRec(NameRec &c): str(NULL)
+       {
+               *this = c;
+       }
+
+       ~NameRec()
+       {
+               if (str)
+                       delete[] str;
+       }
+
+       void operator=(const NameRec &c)
+       {
+               if (this == &c)
+                       return;                                                         // Take care of self-assignment
+
+               if (str)
+                       delete[] str;
+
+               platformID     = c.platformID;
+               platformSpecID = c.platformSpecID;
+               languageID     = c.languageID;
+               nameID         = c.nameID;
+               length         = c.length;
+//Fix this             str            = (uint8 *)strdup((char *)c.str);
+       }
+};
+
+struct Composite
+{
+       uint16 flags, glyphIndex;
+       int16 arg1, arg2;
+       float xScale, yScale, scale01, scale10;
+
+       Composite(uint16 fl = 0, uint16 gl = 0, int16 a1 = 0, int16 a2 = 0,
+               float xs = 1.0f, float ys = 1.0f, float s01 = 1.0f, float s10 = 1.0f):
+               flags(fl), glyphIndex(gl), arg1(a1), arg2(a2), xScale(xs), yScale(ys),
+               scale01(s01), scale10(s10) {}
+};
+
+//
+// The TTF class
+//
+// The following is a set of member functions that needs to be implemented
+// to fully encapsulate a TTF database.
+//
+// SetGlyph(glyphno)
+// DeleteGlyph(glyphno)
+// AddGlyph()
+// GetNumberOfPolys()
+// GetPolyStart(polyno)
+// SetPolyStart(polyno)
+// AddPoly(polyno)
+// DeletePoly(polyno)
+// IsCompositeGlyph()
+// MovePoint(pointno, x, y)
+// AddPoint(pointno, x, y)
+// DeletePoint(pointno)
+// maybe:  TGlyphPt GetPointInfo(pointno) instead of three following...
+// GetPointX(pointno)
+// GetPointY(pointno)
+// GetOnCurve(pointno)
+// SetOnCurve(pointno)
+// ConnectGlyphToChar(glyphno, charno)
+// EncodeGlyph(glyphno)
+// DecodeGlyph(glyphno)
+// GetNumberOfPoints()
+// SwapPoints(pointno1, pointno2)
+//
+// More to be added, as necessary...
+//
+class TTF
+{
+       private:
+               bool EncodeGlyph(uint16);
+               bool DecodeGlyph(uint16);
+               bool ExtractTables(void);
+               bool BuildTables(void);
+
+       public:
+               TTF(void);                                                              // Constructor
+               ~TTF();                                                                 // Destructor
+               void Init(void);                                                // Initalize font database
+               bool Load(const char *);                                // Load font database
+               bool Save(const char *);                                // Save font database
+               void ClearTables(void);                                 // Deallocate memory...
+               bool SetGlyph(uint16 glyphnum);                 // Set internal pointer/encode/decode
+               bool AddGlyph(uint16 glyphnum);
+               bool DeleteGlyph(uint16 glyphnum);
+               Box GetBoundingBox(void);
+               GlyphPt GetPoint(uint16 pointno);
+               uint16 GetNumberOfPolys(void);
+               uint16 GetPolyEnd(uint16 polynum);
+               int GetPointX(uint16 pointno);
+               int GetPointY(uint16 pointno);
+               bool GetOnCurve(uint16 pointno);
+               bool SetOnCurve(uint16 pointno, bool state);
+               bool MovePoint(uint16 pointno, int x, int y);
+               bool MovePoint(uint16 pointno, GlyphPt p);
+               bool AddPoint(uint16 pointno, int x, int y, bool state);
+               bool DeletePoint(uint16 pointno);
+               bool IsCompositeGlyph(void);
+               GlyphPoints GetGlyphPoints(uint16);
+               GlyphPoints GetAllCompositePoints(uint16);
+               void GetCharName(int, uint8 *);
+
+       private:
+               bool isDirty;                                                   // Has glyph been modified?
+               bool isCompositeGlyph;                                  // Is it a composite? (need structs to store composite info...)
+               uint16 currentGlyph;                                    // The glyph currently decoded
+               uint16 numberOfPoints;
+               int gx[MAXPOINTS];                                              // Internal point arrays...
+               int gy[MAXPOINTS];                                              // These could be dynamically allocated in the
+               bool onCurve[MAXPOINTS];                                // constructor, with default values being set
+               uint16 numberOfHints;
+               uint8 hint[MAXHINTS];                                   // Hints storage
+               uint16 numberOfPolys;                                   // Number of polygons in glyph
+               uint16 poly[200];                                               // End points of polygons
+               int16 llx, lly, urx, ury;                               // Lower left/Upper right X/Y
+//     public://remove after debugging...
+               uint8 * glyph[MAXGLYPHS];                               // Placeholders for glyphs
+               uint32 glyphLen[MAXGLYPHS];                             // Glyph lengths are stored since malloc() is sloppy
+               Maxp myMaxp;                                                    // Internal placeholders for this shiat
+               Head myHead;
+//     public: //private: later...
+               List<Composite> compositeList;                  // Composite glyph list
+               uint8 * EBDT, * EBLC, * EBSC, * LTSH, * OS_2, * PCLT, * VDMX, * cmap, * cvt,  * fpgm,
+                       * gasp, * glyf, * hdmx, * head, * hhea, * hmtx, * kern, * loca, * maxp, * name,
+                       * post, * prep, * vhea, * vmtx;
+               uint32 EBDT_len, EBLC_len, EBSC_len, LTSH_len, OS_2_len, PCLT_len, VDMX_len, cmap_len,
+                       cvt_len,  fpgm_len, gasp_len, glyf_len, hdmx_len, head_len, hhea_len, hmtx_len,
+                       kern_len, loca_len, maxp_len, name_len, post_len, prep_len, vhea_len, vmtx_len;
+               uint8 * * parray[24];                                   // Pointer array
+               uint32 * larray[24];                                    // Length array
+               bool loaded;                                                    // Font loaded/init'ed?
+};
+
+#endif // __TTF_H__
+
index cb107ebfab2e30935965ac0015200f8a9258aa3b..0fc13b5e9f768c68af4f83ca369a01ed3f60e50d 100755 (executable)
@@ -1,30 +1,30 @@
-//\r
-// Basic types for platform independent code\r
-//\r
-\r
-#ifndef __TYPES_H__\r
-#define __TYPES_H__\r
-\r
-// This should be portable, since it's part of the C99 standard...!\r
-\r
-#include <stdint.h>\r
-\r
-typedef uint8_t                uint8;\r
-typedef int8_t         int8;\r
-typedef uint16_t       uint16;\r
-typedef int16_t                int16;\r
-typedef uint32_t       uint32;\r
-typedef int32_t                int32;\r
-typedef uint64_t       uint64;\r
-typedef int64_t                int64;\r
-\r
-/*#ifndef _WINDOWS_\r
-#define NULL   0\r
-// This is for non-compliant compilers that don't follow proper scoping rules (and suck). ;-)\r
-#define for if(false);else for\r
-#endif*/\r
-#ifndef NULL\r
-#define NULL    0\r
-#endif\r
-\r
-#endif // __TYPES_H__\r
+//
+// Basic types for platform independent code
+//
+
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+// This should be portable, since it's part of the C99 standard...!
+
+#include <stdint.h>
+
+typedef uint8_t                uint8;
+typedef int8_t         int8;
+typedef uint16_t       uint16;
+typedef int16_t                int16;
+typedef uint32_t       uint32;
+typedef int32_t                int32;
+typedef uint64_t       uint64;
+typedef int64_t                int64;
+
+/*#ifndef _WINDOWS_
+#define NULL   0
+// This is for non-compliant compilers that don't follow proper scoping rules (and suck). ;-)
+#define for if(false);else for
+#endif*/
+#ifndef NULL
+#define NULL    0
+#endif
+
+#endif // __TYPES_H__
index fc008f3e542d9b39f214f69ca7229b365ce70728..7458193e23dc9c8bed39cdbe9cfd2b52396e291e 100755 (executable)
-//\r
-// VECTOR.H - vector class definition\r
-//\r
-// by James L. Hammons\r
-// (C) 2004 Underground Software\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who  When        What\r
-// ---  ----------  -------------------------------------------------------------\r
-// JLH  ??/??/2003  Created original implementation\r
-// JLH  05/14/2004  Separated header from implementation, added operator-\r
-//                  function\r
-// JLH  05/15/2004  Added operator+ function\r
-//\r
-\r
-#include <math.h>\r
-#include "vector.h"\r
-\r
-vector::vector(double a1/*= 0.0*/, double b1/*= 0.0*/, double c1/*= 0.0*/,\r
-       double a2/*= 0.0*/, double b2/*= 0.0*/, double c2/*= 0.0*/):\r
-       x(a1 - a2), y(b1 - b2), z(c1 - c2)\r
-{\r
-}\r
-\r
-vector::vector(const vector &v1, const vector &v2):\r
-       x(v1.x - v2.x), y(v1.y - v2.y), z(v1.z - v2.z)\r
-{\r
-}\r
-\r
-vector& vector::operator=(const vector &v)\r
-{\r
-       x = v.x, y = v.y, z = v.z;\r
-       return *this;\r
-}\r
-\r
-bool vector::operator==(const vector &v)\r
-{\r
-       if ((x == v.x) && (y == v.y) && (z == v.z))\r
-               return true;\r
-\r
-       return false;\r
-}\r
-\r
-void vector::unitize(void)\r
-{\r
-       double dist = sqrt(x*x + y*y + z*z);\r
-\r
-       if (dist != 0.0)\r
-               x /= dist, y /= dist, z /= dist;\r
-\r
-       if (x == -0.0)\r
-               x = +0.0;\r
-\r
-       if (y == -0.0)\r
-               y = +0.0;\r
-\r
-       if (z == -0.0)\r
-               z = +0.0;\r
-}\r
-\r
-vector vector::operator*(const vector &v)              // Cross product: "this" x "v"\r
-{\r
-       vector r;\r
-\r
-       r.x = (y * v.z) - (v.y * z);\r
-       r.y = -((x * v.z) - (v.x * z));\r
-       r.z = (x * v.y) - (v.x * y);\r
-\r
-       return r;\r
-}\r
-\r
-vector vector::operator+(const vector &v)\r
-{\r
-       return vector(x + v.x, y + v.y, z + v.z);\r
-}\r
-\r
-vector vector::operator-(const vector &v)\r
-{\r
-       return vector(x, y, z, v.x, v.y, v.z);\r
-}\r
-\r
-double vector::dot(const vector &v1, const vector &v2)\r
-{\r
-       return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;\r
-}\r
-\r
-double vector::dot(const vector &v)\r
-{\r
-       return x * v.x + y * v.y + z * v.z;\r
-}\r
-\r
-double vector::distance(const vector &v)               // Pythagoras extended to 3 dimensions\r
-{\r
-       double a = x - v.x, b = y - v.y, c = z - v.z;\r
-\r
-       return sqrt(a * a + b * b + c * c);\r
-}\r
-\r
-double vector::length(void)\r
-{\r
-       return sqrt(x * x + y * y + z * z);\r
-}\r
-\r
-void vector::operator*=(const double &d)\r
-{\r
-       x *= d, y *= d, z *= d;\r
-}\r
-\r
-void vector::operator/=(const double &d)\r
-{\r
-       if (d != 0.0)\r
-               x /= d, y /= d, z /= d;\r
-}\r
-\r
-void vector::operator+=(const vector &v)\r
-{\r
-       x += v.x, y += v.y, z += v.z;\r
-}\r
-\r
-void vector::operator-=(const vector &v)\r
-{\r
-       x -= v.x, y -= v.y, z -= v.z;\r
-}\r
-\r
-vector vector::operator*(const double &d)              // Scale vector by amount\r
-{\r
-       return vector(x * d, y * d, z * d);\r
-}\r
-\r
-void vector::zero(const double epsilon)\r
-{\r
-       if (fabs(x) < epsilon)\r
-               x = 0.0;\r
-\r
-       if (fabs(y) < epsilon)\r
-               y = 0.0;\r
-\r
-       if (fabs(z) < epsilon)\r
-               z = 0.0;\r
-}\r
+//
+// VECTOR.H - vector class definition
+//
+// by James L. Hammons
+// (C) 2004 Underground Software
+//
+// JLH = James L. Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  ??/??/2003  Created original implementation
+// JLH  05/14/2004  Separated header from implementation, added operator-
+//                  function
+// JLH  05/15/2004  Added operator+ function
+//
+
+#include <math.h>
+#include "vector.h"
+
+vector::vector(double a1/*= 0.0*/, double b1/*= 0.0*/, double c1/*= 0.0*/,
+       double a2/*= 0.0*/, double b2/*= 0.0*/, double c2/*= 0.0*/):
+       x(a1 - a2), y(b1 - b2), z(c1 - c2)
+{
+}
+
+vector::vector(const vector &v1, const vector &v2):
+       x(v1.x - v2.x), y(v1.y - v2.y), z(v1.z - v2.z)
+{
+}
+
+vector& vector::operator=(const vector &v)
+{
+       x = v.x, y = v.y, z = v.z;
+       return *this;
+}
+
+bool vector::operator==(const vector &v)
+{
+       if ((x == v.x) && (y == v.y) && (z == v.z))
+               return true;
+
+       return false;
+}
+
+void vector::unitize(void)
+{
+       double dist = sqrt(x*x + y*y + z*z);
+
+       if (dist != 0.0)
+               x /= dist, y /= dist, z /= dist;
+
+       if (x == -0.0)
+               x = +0.0;
+
+       if (y == -0.0)
+               y = +0.0;
+
+       if (z == -0.0)
+               z = +0.0;
+}
+
+vector vector::operator*(const vector &v)              // Cross product: "this" x "v"
+{
+       vector r;
+
+       r.x = (y * v.z) - (v.y * z);
+       r.y = -((x * v.z) - (v.x * z));
+       r.z = (x * v.y) - (v.x * y);
+
+       return r;
+}
+
+vector vector::operator+(const vector &v)
+{
+       return vector(x + v.x, y + v.y, z + v.z);
+}
+
+vector vector::operator-(const vector &v)
+{
+       return vector(x, y, z, v.x, v.y, v.z);
+}
+
+double vector::dot(const vector &v1, const vector &v2)
+{
+       return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
+}
+
+double vector::dot(const vector &v)
+{
+       return x * v.x + y * v.y + z * v.z;
+}
+
+double vector::distance(const vector &v)               // Pythagoras extended to 3 dimensions
+{
+       double a = x - v.x, b = y - v.y, c = z - v.z;
+
+       return sqrt(a * a + b * b + c * c);
+}
+
+double vector::length(void)
+{
+       return sqrt(x * x + y * y + z * z);
+}
+
+void vector::operator*=(const double &d)
+{
+       x *= d, y *= d, z *= d;
+}
+
+void vector::operator/=(const double &d)
+{
+       if (d != 0.0)
+               x /= d, y /= d, z /= d;
+}
+
+void vector::operator+=(const vector &v)
+{
+       x += v.x, y += v.y, z += v.z;
+}
+
+void vector::operator-=(const vector &v)
+{
+       x -= v.x, y -= v.y, z -= v.z;
+}
+
+vector vector::operator*(const double &d)              // Scale vector by amount
+{
+       return vector(x * d, y * d, z * d);
+}
+
+void vector::zero(const double epsilon)
+{
+       if (fabs(x) < epsilon)
+               x = 0.0;
+
+       if (fabs(y) < epsilon)
+               y = 0.0;
+
+       if (fabs(z) < epsilon)
+               z = 0.0;
+}
index a7e36ee062ffd59e3bb2a10094fea3c3d1687a07..6f6fa06f1b7cda0fcb67ef2a6b5e2cfd03718e82 100755 (executable)
@@ -1,35 +1,35 @@
-//\r
-// VECTOR.H - vector class definition\r
-//\r
-// by James L. Hammons\r
-// (C) 2003 Underground Software\r
-//\r
-\r
-#ifndef __VECTOR_H__\r
-#define __VECTOR_H__\r
-\r
-struct vector\r
-{\r
-       double x, y, z;\r
-\r
-       vector(double a1=0.0, double b1=0.0, double c1=0.0, double a2=0.0, double b2=0.0, double c2=0.0);\r
-       vector(const vector &v1, const vector &v2);\r
-       vector& operator=(const vector &v);\r
-       bool operator==(const vector &v);\r
-       void unitize(void);\r
-       vector operator*(const vector &v);                      // Cross product: "this" x "v"\r
-       vector operator+(const vector &v);\r
-       vector operator-(const vector &v);\r
-       double dot(const vector &v1, const vector &v2);\r
-       double dot(const vector &v);\r
-       double distance(const vector &v);                       // Pythagoras extended to 3 dimensions\r
-       double length(void);\r
-       void operator*=(const double &d);\r
-       void operator/=(const double &d);\r
-       void operator+=(const vector &v);\r
-       void operator-=(const vector &v);\r
-       vector operator*(const double &d);                      // Scale vector by amount\r
-       void zero(const double epsilon);\r
-};\r
-\r
-#endif // __VECTOR_H__\r
+//
+// VECTOR.H - vector class definition
+//
+// by James L. Hammons
+// (C) 2003 Underground Software
+//
+
+#ifndef __VECTOR_H__
+#define __VECTOR_H__
+
+struct vector
+{
+       double x, y, z;
+
+       vector(double a1=0.0, double b1=0.0, double c1=0.0, double a2=0.0, double b2=0.0, double c2=0.0);
+       vector(const vector &v1, const vector &v2);
+       vector& operator=(const vector &v);
+       bool operator==(const vector &v);
+       void unitize(void);
+       vector operator*(const vector &v);                      // Cross product: "this" x "v"
+       vector operator+(const vector &v);
+       vector operator-(const vector &v);
+       double dot(const vector &v1, const vector &v2);
+       double dot(const vector &v);
+       double distance(const vector &v);                       // Pythagoras extended to 3 dimensions
+       double length(void);
+       void operator*=(const double &d);
+       void operator/=(const double &d);
+       void operator+=(const vector &v);
+       void operator-=(const vector &v);
+       vector operator*(const double &d);                      // Scale vector by amount
+       void zero(const double epsilon);
+};
+
+#endif // __VECTOR_H__