-/* 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",
+" ...............................",
+" ..............................",
+" .............................",
+" ............................",
+" ...........................",
+" ..........................",
+" .........................",
+" ........................",
+" .......................",
+" ......................",
+" .....................",
+" ....................",
+" .........................",
+" .........................",
+" .. ........................",
+" ... ........................",
+" ..... .......................",
+"...... .......................",
+"....... ......................",
+"....... .......................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
-/* 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",
+" ...............................",
+" ..............................",
+" .............................",
+" ............................",
+" ...........................",
+" ..........................",
+" .........................",
+" ........................",
+" .......................",
+" ......................",
+" .....................",
+" ....................",
+" .........................",
+" ...... .............",
+" .. ..... ............",
+" ... ..... ... ............",
+" ..... .... ... ............",
+"...... .... ... ............",
+"....... ... ............",
+"....... .... .............",
+"............. .................",
+"............. .................",
+"............. .................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
-/* 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",
+" .. ",
+" .. ",
+" .... ",
+" .... ",
+" ...... ",
+" . .. . ",
+" . .. . ",
+" .. ",
+" .. .. .. ",
+" ... . . ... ",
+"......... .. ......... ",
+"......... .. ......... ",
+" ... . . ... ",
+" .. .. .. ",
+" .. ",
+" . .. . ",
+" . .. . ",
+" ...... ",
+" ..... ",
+" .... ",
+" .. ",
+" .. ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
-/* 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",
+" .. ",
+" .. ",
+"...... ",
+"...... ",
+" .. ",
+" .. ",
+" ... ",
+" .. .. .. ",
+" .. .. .. ",
+" .... . . . ",
+" .... . . . ",
+"...... . . . ",
+". .. . . . . ",
+" .. . . ",
+" .. . . ",
+" .. . . ",
+" .. .. .. ",
+" .. .. ... ",
+" .. ... . ",
+". .. . . ",
+"...... .. ",
+" .... ... ",
+" .... ... ",
+" .. ... ",
+" .. . ",
+" ",
+" ",
+"...... ",
+"...... ",
+" ",
+" ",
+" "};
-/* 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",
+" ...............................",
+" ..............................",
+" .............................",
+" ............................",
+" ...........................",
+" ..........................",
+" .........................",
+" ........................",
+" .......................",
+" ......................",
+" .....................",
+" ....................",
+" .........................",
+" ...... ..................",
+" .. .... .................",
+" ... ..... ..................",
+" ..... .......................",
+"...... ..... ..............",
+"....... ... .............",
+"....... .... .. .............",
+"............. .. .............",
+"............. .............",
+".............. ..............",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
-/* 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",
+" ...............................",
+" ..............................",
+" .............................",
+" ............................",
+" ...........................",
+" ..........................",
+" .........................",
+" ........................",
+" .......................",
+" ......................",
+" .....................",
+" ....................",
+" ........ ...............",
+" ....... ..............",
+" .. ...... ..............",
+" ... ..... .. .............",
+" ..... .... .. .............",
+"...... ... .... ............",
+"....... .. .... ............",
+"....... .. ...... ...........",
+"........... ...... ...........",
+".......... ........ ..........",
+".......... ..........",
+"........... ...........",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
-/* 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",
+" ...............................",
+" ..............................",
+" .............................",
+" ............................",
+" ...........................",
+" ..........................",
+" .........................",
+" ........................",
+" .......................",
+" ......................",
+" .....................",
+" ....................",
+" .........................",
+" .........................",
+" .. ........................",
+" ... ... ...... ...........",
+" ..... .. .... ...........",
+"...... ... ............",
+"....... ... .............",
+"....... .... .............",
+"............. .............",
+"............. .............",
+"............ ............",
+"........... .... ...........",
+"........... ...... ...........",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
-/* 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",
+" ...............................",
+" ..............................",
+" .............................",
+" ............................",
+" ...........................",
+" ..........................",
+" .........................",
+" ........................",
+" .......................",
+" ......................",
+" .....................",
+" ....................",
+" .........................",
+" .........................",
+" .. ........................",
+" ... ... ...... ...........",
+" ..... .. .... ...........",
+"...... ... ............",
+"....... ... .............",
+"....... .... .............",
+"............. .............",
+"............. .............",
+"............ ............",
+"........... .... ...........",
+"........... ...... ...........",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"};
-/* 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",
+" ",
+" ",
+" ",
+" ",
+" ++ ",
+" ++ ",
+" ++++ ",
+" ++++++++++++++ ",
+" ++++ ",
+" ++ ",
+" ++ ",
+" ",
+" ",
+" ",
+" "};
-/* 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",
+" ",
+" ",
+" ",
+" ",
+" ++ ",
+" ++ ",
+" ++++ ",
+" ++++++++++++++ ",
+" ++++ ",
+" ++ ",
+" ++ ",
+" ",
+" ",
+" ",
+" "};
-/* 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",
+"++++++++++++++++",
+"+ +",
+"+ ++++++++ +",
+"+ ++++++++++ +",
+"+ ++ ++ +",
+"+ ++ +",
+"+ +++++++++ +",
+"+ ++++++++++ +",
+"+ ++ ++ +",
+"+ ++ ++ +",
+"+ ++ +++ +",
+"+ ++++++++++ +",
+"+ ++++++ ++ +",
+"+ +",
+"++++++++++++++++"};
+
-/* 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",
+" ",
+" .................. .................. .................. .................. ",
+" ",
+" . .................. . . .................. . . .................. . . .................. . ",
+" . .... ............. . . .................. . . ........ ........ . . .................. . ",
+" . .... ............ . . .................. . . ........ ........ . . ...... .......... . ",
+" . .... ........... . . .. ............... . . ....... ....... . . .... .. ........ . ",
+" . .... .......... . . .. .............. . . ....... ....... . . ... ...... ....... . ",
+" . .... ......... . . .. ............. . . ...... . . ...... . . ... ...... ....... . ",
+" . .... ........ . . .. ............ . . ..... .. .. ..... . . .. ........ ...... . ",
+" . .... ....... . . .. ... .. . . ... ... ... ... . . .. ........ ...... . ",
+" . .... ...... . . .. .. . . . . . . . ... ...... ....... . ",
+" . .... ..... . . .. . ... . . . . . . . ... ...... ....... . ",
+" . .... ........ . . .. ... ... . . . ... ... ... ... . . .... .. ...... . ",
+" . .... ........ . . .. ... . . . ..... .. .. ..... . . ...... .. ..... . ",
+" . .... .. ....... . . .. .. .. .. . . ...... . . ...... . . ........... .... . ",
+" . .... ... ....... . . ...... .. ...... . . ....... ....... . . ............ ... . ",
+" . ......... ...... . . .......... ...... . . ....... ....... . . ............. .. . ",
+" . ......... ...... . . .......... ...... . . ........ ........ . . .............. .. . ",
+" . .......... ....... . . .................. . . ........ ........ . . .................. . ",
+" . .................. . . .................. . . .................. . . .................. . ",
+" ",
+" .................. .................. .................. .................. ",
+" ",
+" ",
+" .................. .................. .................. .................. ",
+" ",
+" . .................. . . .................. . . .................. . . .................. . ",
+" . .................. . . .................. . . .................. . . .................. . ",
+" . .................. . . ........ ........ . . .. .......... .. . . .. ........... .. . ",
+" . .................. . . ....... ....... . . .. ........ .. . . ... . .. .. . ",
+" . .................. . . ....... ....... . . ... ...... ... . . .... ... . ",
+" . ....... ....... . . ...... .. ...... . . .... .... . . ..... ... .... . ",
+" . ...... ...... . . ...... .. ...... . . ..... ..... . . ...... ... ..... . ",
+" . ..... ..... . . ..... .... ..... . . ..... ..... . . ...... . ..... . ",
+" . ..... .. ..... . . ..... .... ..... . . ..... ..... . . ...... ..... . ",
+" . ..... .. ..... . . .... ...... .... . . ..... ..... . . ...... ..... . ",
+" . ..... ..... . . .... ...... .... . . ..... ..... . . ...... ...... . ",
+" . ...... ...... . . ... ........ ... . . ..... ..... . . ...... ... ..... . ",
+" . ....... ....... . . ... ........ ... . . .... .... . . ..... .... .... . ",
+" . .................. . . .. .......... .. . . ... ...... ... . . .... ..... ... . ",
+" . .................. . . .. .. . . .. ........ .. . . ... . ...... .. . ",
+" . .................. . . ... ... . . .. .......... .. . . .. ........... .. . ",
+" . .................. . . .................. . . .................. . . .................. . ",
+" . .................. . . .................. . . .................. . . .................. . ",
+" ",
+" .................. .................. .................. .................. ",
+" "};
-//\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
+
+*/
+
-//\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;
+
+};*/
+
-//\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);
+}
-//\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__
-//\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;
+}
+//*/
-//\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);
+
-//\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
-//\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__
-//\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;
+}
+
-//\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__
-//\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);
+}
-//\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__
-//\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;
+}
-//\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
-//\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__
-//\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;
+}
-//\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__
-//\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
+
-//\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();
+}
-//\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__
-//\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] = <SH; 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] = <SH_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] = <SH; 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] = <SH_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;
+}
+
-//\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__
+
-//\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__
-//\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;
+}
-//\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__