From: Shamus Hammons Date: Tue, 29 May 2007 17:15:58 +0000 (+0000) Subject: Move main repo to trunk. X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;ds=sidebyside;h=6d13a5166688e470590692eb91c3915ab332fe36;p=ttedit Move main repo to trunk. --- 6d13a5166688e470590692eb91c3915ab332fe36 diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..75a82fa --- /dev/null +++ b/Makefile @@ -0,0 +1,184 @@ +# +# Makefile for TrueType Edit +# +# Author: James Hammons +# Copyright: (c) 2006 Underground Software +# + +ifeq "$(OSTYPE)" "msys" # Win32 + +SYSTYPE = __GCCWIN32__ +EXESUFFIX = .exe +ICON = obj/icon.o +MSG = Win32 on MinGW + +else +#ifeq "$(OSTYPE)" "darwin" +ifeq "darwin" "$(findstring darwin,$(OSTYPE))" # Should catch both 'darwin' and 'darwin7.0' + +SYSTYPE = __GCCUNIX__ -D_OSX_ +EXESUFFIX = +ICON = +MSG = Mac OS X + +else # *nix + +SYSTYPE = __GCCUNIX__ +EXESUFFIX = +ICON = +MSG = generic Unix/Linux + +endif +endif + +# This is ugly, ugly, ugly. Find a way to fix this crap so it's more unified, +# like the SDL based makefiles are... !!! FIX !!! [made initial stab at it] + +### Variables: ### + +#EXEEXT = .exe +RESCOMP = windres +srcdir = ./src +top_srcdir = /local +top_builddir = /local/ +CXX = g++ +TOOLKIT = MSW +TOOLKIT_LOWERCASE = msw +WX_RELEASE = 2.6 +WX_VERSION = $(WX_RELEASE).0 + +# This is OK + +# Note that the -MMD flag is what gives us our automagic dependency information (*.d files) +# Add -g to compile in debuggin information +CXXFLAGS = -MMD -Wall -Wno-switch -Wno-non-virtual-dtor -O2 `wx-config --cxxflags` -g +INCS = -I. +LIBS = `wx-config --libs` + +PROGRAM = ttedit + +# KO si sihT + +OBJECTS = \ + obj/bezier.o \ + obj/charnames.o \ + obj/debug.o \ + obj/glyphpoints.o \ + obj/registry.o \ + obj/ttf.o \ + obj/vector.o \ + obj/$(PROGRAM).o \ + $(ICON) + +BIN_PROGRAM = $(PROGRAM)$(EXESUFFIX) +#Need to fix this shit +ifneq "" "$(ICON)" +RES_PROGRAM_OBJ = obj/$(PROGRAM)_resources.o +else +RES_PROGRAM_OBJ = +endif +BUNDLE = $(BIN_PROGRAM).app/Contents + +### Conditionally set variables: ### + +COND_TOOLKIT_MAC___MACOSX_RESOURCES_p_1 = $(RESCOMP) -d __DARWIN__ -t APPL -d \ + __WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p_1) $(__EXCEPTIONS_DEFINE_p_1) \ + $(__RTTI_DEFINE_p_1) $(__THREAD_DEFINE_p_1) -i $(srcdir) -d WXUSINGDLL -i \ + $(srcdir)/../../samples -i $(top_srcdir)/include -o bombs$(EXEEXT) Carbon.r \ + sample.r + +### Targets: ### + +all: checkenv message obj $(BIN_PROGRAM) $(__bombs_bundle___depname) + @echo + @echo "*** Looks like it compiled OK... Give it a whirl!" + +obj: + @mkdir obj + +#install: all + +# Check the compilation environment, barf if not appropriate + +checkenv: + @echo + @echo -n "*** Checking compilation environment... " +ifeq "" "$(shell which wx-config)" + @echo + @echo + @echo "It seems that you don't have the wxWidget development libraries installed." + @echo "If you have installed them, make sure that the wx-config file is somewhere" + @echo "in your path and is executable." + @echo +#Is there a better way to break out of the makefile? +# @break + @breakola! +else + @echo "OK" +endif + +message: +# @echo + @echo "*** Building TTEdit for $(MSG)..." + @echo + +clean: + @echo -n "*** Cleaning out the garbage..." + @rm -rf ./obj + @rm -f $(BIN_PROGRAM) +# rm -rf bombs.app + @echo "done!" + +## This is only done for Win32 at the moment... +# +#ifneq "" "$(ICON)" +#$(ICON): res/$(TARGET).rc res/$(TARGET).ico +# @echo "*** Processing icon..." +# @windres -i res/$(TARGET).rc -o $(ICON) --include-dir=./res +#endif + +# This is only done for Win32 at the moment... + +ifneq "" "$(ICON)" +$(RES_PROGRAM_OBJ): res/$(PROGRAM).rc res/$(PROGRAM).ico + @echo "*** Processing icon..." + @$(RESCOMP) -i$< -o$@ --define __WX$(TOOLKIT)__ --include-dir ./res --define WXUSINGDLL --include-dir $(top_srcdir)/include/wx-2.6 +endif + +obj/%.o: $(srcdir)/%.cpp + @echo "*** Compiling $<..." + @$(CXX) -c -o $@ $(INCS) $(CXXFLAGS) $< + +$(BIN_PROGRAM): $(OBJECTS) $(RES_PROGRAM_OBJ) + @echo "*** Linking it all together..." + @$(CXX) -o $@ $(OBJECTS) $(RES_PROGRAM_OBJ) $(LIBS) +# $(_mac_rezcmd) +# $(_mac_setfilecmd) + +# Mac OSX bundling shit (figure out how to condense this so it works!) + +bombs.app/Contents/PkgInfo: bombs$(EXEEXT) $(top_srcdir)/src/mac/carbon/Info.plist.in $(top_srcdir)/src/mac/carbon/wxmac.icns + mkdir -p bombs.app/Contents + mkdir -p bombs.app/Contents/MacOS + mkdir -p bombs.app/Contents/Resources + + sed -e "s/IDENTIFIER/`echo $(srcdir) | sed -e 's,\.\./,,g' | sed -e 's,/,.,g'`/" \ + -e "s/EXECUTABLE/bombs/" \ + -e "s/VERSION/$(WX_VERSION)/" \ + $(top_srcdir)/src/mac/carbon/Info.plist.in >bombs.app/Contents/Info.plist + + echo -n "APPL????" >bombs.app/Contents/PkgInfo + + ln -f bombs$(EXEEXT) bombs.app/Contents/MacOS/bombs + + cp -f $(top_srcdir)/src/mac/carbon/wxmac.icns bombs.app/Contents/Resources/wxmac.icns + +#bundle: $(_BUNDLE_TGT_REF_DEP) + +### Include dependency info, if present: + +-include ./obj/*.d + +### No idea what this does + +#.PHONY: all install uninstall clean distclean bundle diff --git a/res/cur1.xpm b/res/cur1.xpm new file mode 100755 index 0000000..46c1adf --- /dev/null +++ b/res/cur1.xpm @@ -0,0 +1,37 @@ +/* XPM */ +static char * cur1_xpm[] = { +"32 32 2 1", +" g #000000", +". g #FFFFFF", +" ...............................", +" ..............................", +" .............................", +" ............................", +" ...........................", +" ..........................", +" .........................", +" ........................", +" .......................", +" ......................", +" .....................", +" ....................", +" .........................", +" .........................", +" .. ........................", +" ... ........................", +" ..... .......................", +"...... .......................", +"....... ......................", +"....... .......................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................"}; diff --git a/res/cur2.xpm b/res/cur2.xpm new file mode 100755 index 0000000..4a33bca --- /dev/null +++ b/res/cur2.xpm @@ -0,0 +1,37 @@ +/* XPM */ +static char * cur2_xpm[] = { +"32 32 2 1", +" g #000000", +". g #FFFFFF", +" ...............................", +" ..............................", +" .............................", +" ............................", +" ...........................", +" ..........................", +" .........................", +" ........................", +" .......................", +" ......................", +" .....................", +" ....................", +" .........................", +" ...... .............", +" .. ..... ............", +" ... ..... ... ............", +" ..... .... ... ............", +"...... .... ... ............", +"....... ... ............", +"....... .... .............", +"............. .................", +"............. .................", +"............. .................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................"}; diff --git a/res/cur3.xpm b/res/cur3.xpm new file mode 100755 index 0000000..595a360 --- /dev/null +++ b/res/cur3.xpm @@ -0,0 +1,37 @@ +/* XPM */ +static char * cur3_xpm[] = { +"32 32 2 1", +" g #FFFFFF", +". g #000000", +" .. ", +" .. ", +" .... ", +" .... ", +" ...... ", +" . .. . ", +" . .. . ", +" .. ", +" .. .. .. ", +" ... . . ... ", +"......... .. ......... ", +"......... .. ......... ", +" ... . . ... ", +" .. .. .. ", +" .. ", +" . .. . ", +" . .. . ", +" ...... ", +" ..... ", +" .... ", +" .. ", +" .. ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/res/cur4.xpm b/res/cur4.xpm new file mode 100755 index 0000000..86c2141 --- /dev/null +++ b/res/cur4.xpm @@ -0,0 +1,37 @@ +/* XPM */ +static char * cur4_xpm[] = { +"32 32 2 1", +" g #FFFFFF", +". g #000000", +" .. ", +" .. ", +"...... ", +"...... ", +" .. ", +" .. ", +" ... ", +" .. .. .. ", +" .. .. .. ", +" .... . . . ", +" .... . . . ", +"...... . . . ", +". .. . . . . ", +" .. . . ", +" .. . . ", +" .. . . ", +" .. .. .. ", +" .. .. ... ", +" .. ... . ", +". .. . . ", +"...... .. ", +" .... ... ", +" .... ... ", +" .. ... ", +" .. . ", +" ", +" ", +"...... ", +"...... ", +" ", +" ", +" "}; diff --git a/res/cur5.xpm b/res/cur5.xpm new file mode 100755 index 0000000..9bc1b35 --- /dev/null +++ b/res/cur5.xpm @@ -0,0 +1,37 @@ +/* XPM */ +static char * cur5_xpm[] = { +"32 32 2 1", +" g #000000", +". g #FFFFFF", +" ...............................", +" ..............................", +" .............................", +" ............................", +" ...........................", +" ..........................", +" .........................", +" ........................", +" .......................", +" ......................", +" .....................", +" ....................", +" .........................", +" .........................", +" .. ........................", +" ... ........................", +" ..... .......................", +"...... ..... ..............", +"....... ... .............", +"....... .... .. .............", +"............. .. .............", +"............. .............", +".............. ..............", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................"}; diff --git a/res/cur6.xpm b/res/cur6.xpm new file mode 100755 index 0000000..bf24733 --- /dev/null +++ b/res/cur6.xpm @@ -0,0 +1,37 @@ +/* XPM */ +static char * cur6_xpm[] = { +"32 32 2 1", +" g #000000", +". g #FFFFFF", +" ...............................", +" ..............................", +" .............................", +" ............................", +" ...........................", +" ..........................", +" .........................", +" ........................", +" .......................", +" ......................", +" .....................", +" ....................", +" ........ ...............", +" ....... ..............", +" .. ...... ..............", +" ... ..... .. .............", +" ..... .... .. .............", +"...... ... .... ............", +"....... .. .... ............", +"....... .. ...... ...........", +"........... ...... ...........", +".......... ........ ..........", +".......... ..........", +"........... ...........", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................"}; diff --git a/res/cur7.xpm b/res/cur7.xpm new file mode 100755 index 0000000..1c9fb67 --- /dev/null +++ b/res/cur7.xpm @@ -0,0 +1,37 @@ +/* XPM */ +static char * cur7_xpm[] = { +"32 32 2 1", +" g #000000", +". g #FFFFFF", +" ...............................", +" ..............................", +" .............................", +" ............................", +" ...........................", +" ..........................", +" .........................", +" ........................", +" .......................", +" ......................", +" .....................", +" ....................", +" .........................", +" .........................", +" .. ........................", +" ... ... ...... ...........", +" ..... .. .... ...........", +"...... ... ............", +"....... ... .............", +"....... .... .............", +"............. .............", +"............. .............", +"............ ............", +"........... .... ...........", +"........... ...... ...........", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................"}; diff --git a/res/cur8.xpm b/res/cur8.xpm new file mode 100755 index 0000000..91d96a5 --- /dev/null +++ b/res/cur8.xpm @@ -0,0 +1,37 @@ +/* XPM */ +static char * cur8_xpm[] = { +"32 32 2 1", +" g #000000", +". g #FFFFFF", +" ...............................", +" ..............................", +" .............................", +" ............................", +" ...........................", +" ..........................", +" .........................", +" ........................", +" .......................", +" ......................", +" .....................", +" ....................", +" .........................", +" .........................", +" .. ........................", +" ... ... ...... ...........", +" ..... .. .... ...........", +"...... ... ............", +"....... ... .............", +"....... .... .............", +"............. .............", +"............. .............", +"............ ............", +"........... .... ...........", +"........... ...... ...........", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................"}; diff --git a/res/tool1.xpm b/res/tool1.xpm new file mode 100755 index 0000000..200b8c6 --- /dev/null +++ b/res/tool1.xpm @@ -0,0 +1,21 @@ +/* XPM */ +static char * tool1_xpm[] = { +"16 15 3 1", +" c None", +". c #A0A0A0", +"+ c #000000", +" ", +" ", +" ", +" ", +" ++ ", +" ++ ", +" ++++ ", +" ++++++++++++++ ", +" ++++ ", +" ++ ", +" ++ ", +" ", +" ", +" ", +" "}; diff --git a/res/tool2.xpm b/res/tool2.xpm new file mode 100755 index 0000000..9343889 --- /dev/null +++ b/res/tool2.xpm @@ -0,0 +1,21 @@ +/* XPM */ +static char * tool2_xpm[] = { +"16 15 3 1", +" c None", +". c #C0C0C0", +"+ c #000000", +" ", +" ", +" ", +" ", +" ++ ", +" ++ ", +" ++++ ", +" ++++++++++++++ ", +" ++++ ", +" ++ ", +" ++ ", +" ", +" ", +" ", +" "}; diff --git a/res/tool3.xpm b/res/tool3.xpm new file mode 100755 index 0000000..06d0c06 --- /dev/null +++ b/res/tool3.xpm @@ -0,0 +1,22 @@ +/* XPM */ +static char * tool3_xpm[] = { +"16 15 3 1", +" c None", +". c #C0C0C0", +"+ c #000000", +"++++++++++++++++", +"+ +", +"+ ++++++++ +", +"+ ++++++++++ +", +"+ ++ ++ +", +"+ ++ +", +"+ +++++++++ +", +"+ ++++++++++ +", +"+ ++ ++ +", +"+ ++ ++ +", +"+ ++ +++ +", +"+ ++++++++++ +", +"+ ++++++ ++ +", +"+ +", +"++++++++++++++++"}; + diff --git a/res/toolpal1.xpm b/res/toolpal1.xpm new file mode 100755 index 0000000..a11c7a9 --- /dev/null +++ b/res/toolpal1.xpm @@ -0,0 +1,53 @@ +/* XPM */ +static char * toolpal1_xpm[] = { +"96 48 2 1", +" c #000000", +". c #FFFFFF", +" ", +" .................. .................. .................. .................. ", +" ", +" . .................. . . .................. . . .................. . . .................. . ", +" . .... ............. . . .................. . . ........ ........ . . .................. . ", +" . .... ............ . . .................. . . ........ ........ . . ...... .......... . ", +" . .... ........... . . .. ............... . . ....... ....... . . .... .. ........ . ", +" . .... .......... . . .. .............. . . ....... ....... . . ... ...... ....... . ", +" . .... ......... . . .. ............. . . ...... . . ...... . . ... ...... ....... . ", +" . .... ........ . . .. ............ . . ..... .. .. ..... . . .. ........ ...... . ", +" . .... ....... . . .. ... .. . . ... ... ... ... . . .. ........ ...... . ", +" . .... ...... . . .. .. . . . . . . . ... ...... ....... . ", +" . .... ..... . . .. . ... . . . . . . . ... ...... ....... . ", +" . .... ........ . . .. ... ... . . . ... ... ... ... . . .... .. ...... . ", +" . .... ........ . . .. ... . . . ..... .. .. ..... . . ...... .. ..... . ", +" . .... .. ....... . . .. .. .. .. . . ...... . . ...... . . ........... .... . ", +" . .... ... ....... . . ...... .. ...... . . ....... ....... . . ............ ... . ", +" . ......... ...... . . .......... ...... . . ....... ....... . . ............. .. . ", +" . ......... ...... . . .......... ...... . . ........ ........ . . .............. .. . ", +" . .......... ....... . . .................. . . ........ ........ . . .................. . ", +" . .................. . . .................. . . .................. . . .................. . ", +" ", +" .................. .................. .................. .................. ", +" ", +" ", +" .................. .................. .................. .................. ", +" ", +" . .................. . . .................. . . .................. . . .................. . ", +" . .................. . . .................. . . .................. . . .................. . ", +" . .................. . . ........ ........ . . .. .......... .. . . .. ........... .. . ", +" . .................. . . ....... ....... . . .. ........ .. . . ... . .. .. . ", +" . .................. . . ....... ....... . . ... ...... ... . . .... ... . ", +" . ....... ....... . . ...... .. ...... . . .... .... . . ..... ... .... . ", +" . ...... ...... . . ...... .. ...... . . ..... ..... . . ...... ... ..... . ", +" . ..... ..... . . ..... .... ..... . . ..... ..... . . ...... . ..... . ", +" . ..... .. ..... . . ..... .... ..... . . ..... ..... . . ...... ..... . ", +" . ..... .. ..... . . .... ...... .... . . ..... ..... . . ...... ..... . ", +" . ..... ..... . . .... ...... .... . . ..... ..... . . ...... ...... . ", +" . ...... ...... . . ... ........ ... . . ..... ..... . . ...... ... ..... . ", +" . ....... ....... . . ... ........ ... . . .... .... . . ..... .... .... . ", +" . .................. . . .. .......... .. . . ... ...... ... . . .... ..... ... . ", +" . .................. . . .. .. . . .. ........ .. . . ... . ...... .. . ", +" . .................. . . ... ... . . .. .......... .. . . .. ........... .. . ", +" . .................. . . .................. . . .................. . . .................. . ", +" . .................. . . .................. . . .................. . . .................. . ", +" ", +" .................. .................. .................. .................. ", +" "}; diff --git a/res/ttedit.xpm b/res/ttedit.xpm new file mode 100755 index 0000000..9828fe0 --- /dev/null +++ b/res/ttedit.xpm @@ -0,0 +1,46 @@ +/* XPM */ +static char *ttedit_xpm[]={ +"32 32 11 1", +". c None", +"d c #0000ff", +"a c #00ffff", +"i c #600000", +"# c #600040", +"h c #606040", +"b c #6060ff", +"g c #a0a080", +"c c #ff0000", +"f c #ff6040", +"e c #ffffff", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................", +".##############.................", +".##############.................", +".##...####...##............aab..", +".#....####....#..........aabbbb.", +"......##cc.c.c.c.c.c.c.aabbbbbb.", +"......##c#c.c...c.c..aabbbbbbdd.", +"......###c...c.....aabbbbbbdd...", +"......##c#......c.ebbbbbbdd.....", +"......####...c...fgbbbbdd.......", +"......####......fccgbdd.........", +"......####...c.fccchd...........", +"......####....ciiii.............", +"......####...cc.................", +"......####...cccc...............", +".....######..cccc...............", +".............cccc...............", +".............cccc...............", +".............cccc...............", +"............cccccc..............", +"................................", +"................................", +"................................", +"................................", +"................................", +"................................"}; diff --git a/src/bezier.cpp b/src/bezier.cpp new file mode 100755 index 0000000..415f381 --- /dev/null +++ b/src/bezier.cpp @@ -0,0 +1,45 @@ +// +// Bezier curve fitter +// by James L. Hammons +// (C) 2005 Underground Software +// +// This function takes three points and draws a curve using a +// second order Bezier function. +// +// JLH = James L. Hammons +// +// Who When What +// --- ---------- ------------------------------------------------------------- +// JLH 03/14/1998 Created this file +// JLH 01/20/2005 Converted to use wxWidgets +// + +#include "bezier.h" + +double abs(double n) // Helper function +{ + return (n < 0 ? -n : n); +} + +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 + +// MoveToEx(hdc, (int)p1.x, (int)p1.y, NULL); + 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, + x = (p1.x * (1 - _2u + _uu)) + (p2.x * (_2u - _2uu)) + (p3.x * _uu), + y = (p1.y * (1 - _2u + _uu)) + (p2.y * (_2u - _2uu)) + (p3.y * _uu); +// LineTo(hdc, (int)x, (int)y); + dc.DrawLine(prevX, prevY, (wxCoord)x, (wxCoord)y); + prevX = (wxCoord)x, prevY = (wxCoord)y; + } + +// LineTo(hdc, (int)p3.x, (int)p3.y); + dc.DrawLine(prevX, prevY, (wxCoord)p3.x, (wxCoord)p3.y); +} diff --git a/src/bezier.h b/src/bezier.h new file mode 100755 index 0000000..4a5c5ee --- /dev/null +++ b/src/bezier.h @@ -0,0 +1,22 @@ +// True Type Hack +// +// Bezier Curve fitter header +// +// This function takes three points and draws a curve using a +// second order Bezier function. + +#ifndef __BEZIER_H__ +#define __BEZIER_H__ + +#include // For device context + +struct point +{ + float x, y; + + point(float xx = 0, float yy = 0): x(xx), y(yy) {} +}; + +void Bezier(wxDC &, point, point, point); + +#endif // __BEZIER_H__ diff --git a/src/charnames.cpp b/src/charnames.cpp new file mode 100755 index 0000000..84eaf30 --- /dev/null +++ b/src/charnames.cpp @@ -0,0 +1,2632 @@ +// +// 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 +// +// 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 + = DELETE +@@ 0080 C1 Controls and Latin-1 Supplement (Latin-1 Supplement) 00FF +@ C1 controls +@+ Alias names are those for ISO 6429. +0080 +0081 +0082 + = BREAK PERMITTED HERE +0083 + = NO BREAK HERE +0084 +0085 + = NEXT LINE +0086 + = START OF SELECTED AREA +0087 + = END OF SELECTED AREA +0088 + = CHARACTER TABULATION SET +0089 + = CHARACTER TABULATION WITH JUSTIFICATION +008A + = LINE TABULATION SET +008B + = PARTIAL LINE DOWN +008C + = PARTIAL LINE UP +008D + = REVERSE LINE FEED +008E + = SINGLE SHIFT TWO +008F + = SINGLE SHIFT THREE +0090 + = DEVICE CONTROL STRING +0091 + = PRIVATE USE ONE +0092 + = PRIVATE USE TWO +0093 + = SET TRANSMIT STATE +0094 + = CANCEL CHARACTER +0095 + = MESSAGE WAITING +0096 + = START OF GUARDED AREA +0097 + = END OF GUARDED AREA +0098 + = START OF STRING +0099 +009A + = SINGLE CHARACTER INTRODUCER +009B + = CONTROL SEQUENCE INTRODUCER +009C + = STRING TERMINATOR +009D + = OPERATING SYSTEM COMMAND +009E + = PRIVACY MESSAGE +009F + = 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) + # 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 + # 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) + # 0032 +00B3 SUPERSCRIPT THREE + = cubed + x (superscript one - 00B9) + # 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) + # 0031 +00BA MASCULINE ORDINAL INDICATOR + * Spanish + # 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 + # 0068 +02B1 MODIFIER LETTER SMALL H WITH HOOK + * breathy voiced, murmured + x (latin small letter h with hook - 0266) + x (combining diaeresis below - 0324) + # 0266 +02B2 MODIFIER LETTER SMALL J + * palatalization + x (combining palatalized hook below - 0321) + # 006A +02B3 MODIFIER LETTER SMALL R + # 0072 +02B4 MODIFIER LETTER SMALL TURNED R + x (latin small letter turned r - 0279) + # 0279 +02B5 MODIFIER LETTER SMALL TURNED R WITH HOOK + x (latin small letter turned r with hook - 027B) + # 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) + # 0281 +02B7 MODIFIER LETTER SMALL W + * labialization + x (combining inverted double arch below - 032B) + # 0077 +02B8 MODIFIER LETTER SMALL Y + * palatalization + * common Americanist substitution for 02B2 + # 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 + # 0263 +02E1 MODIFIER LETTER SMALL L + # 006C +02E2 MODIFIER LETTER SMALL S + # 0073 +02E3 MODIFIER LETTER SMALL X + # 0078 +02E4 MODIFIER LETTER SMALL REVERSED GLOTTAL STOP + # 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 + # 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) + # 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) + # 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 + # 0030 +2071 + x (superscript one - 00B9) +2072 + x (superscript two - 00B2) +2073 + x (superscript three - 00B3) +2074 SUPERSCRIPT FOUR + # 0034 +2075 SUPERSCRIPT FIVE + # 0035 +2076 SUPERSCRIPT SIX + # 0036 +2077 SUPERSCRIPT SEVEN + # 0037 +2078 SUPERSCRIPT EIGHT + # 0038 +2079 SUPERSCRIPT NINE + # 0039 +207A SUPERSCRIPT PLUS SIGN + # 002B +207B SUPERSCRIPT MINUS + # 2212 +207C SUPERSCRIPT EQUALS SIGN + # 003D +207D SUPERSCRIPT LEFT PARENTHESIS + # 0028 +207E SUPERSCRIPT RIGHT PARENTHESIS + # 0029 +207F SUPERSCRIPT LATIN SMALL LETTER N + # 006E +@ Subscripts +2080 SUBSCRIPT ZERO + # 0030 +2081 SUBSCRIPT ONE + # 0031 +2082 SUBSCRIPT TWO + # 0032 +2083 SUBSCRIPT THREE + # 0033 +2084 SUBSCRIPT FOUR + # 0034 +2085 SUBSCRIPT FIVE + # 0035 +2086 SUBSCRIPT SIX + # 0036 +2087 SUBSCRIPT SEVEN + # 0037 +2088 SUBSCRIPT EIGHT + # 0038 +2089 SUBSCRIPT NINE + # 0039 +208A SUBSCRIPT PLUS SIGN + # 002B +208B SUBSCRIPT MINUS + # 2212 +208C SUBSCRIPT EQUALS SIGN + # 003D +208D SUBSCRIPT LEFT PARENTHESIS + # 0028 +208E SUBSCRIPT RIGHT PARENTHESIS + # 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 + +*/ + diff --git a/src/charnames.h b/src/charnames.h new file mode 100755 index 0000000..53d357c --- /dev/null +++ b/src/charnames.h @@ -0,0 +1,18 @@ +// +// 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; + +};*/ + diff --git a/src/debug.cpp b/src/debug.cpp new file mode 100755 index 0000000..b165165 --- /dev/null +++ b/src/debug.cpp @@ -0,0 +1,206 @@ +// +// DEBUG.CPP: Debugging support +// by James L. Hammons +// (C) 2002 Underground Software +// +// JLH = James Hammons +// +// 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 +//#include +#include +#include +#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; +} +//*/ diff --git a/src/debug.h b/src/debug.h new file mode 100755 index 0000000..b53a15d --- /dev/null +++ b/src/debug.h @@ -0,0 +1,15 @@ +// +// 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); + diff --git a/src/glyphpoints.cpp b/src/glyphpoints.cpp new file mode 100755 index 0000000..a2b80aa --- /dev/null +++ b/src/glyphpoints.cpp @@ -0,0 +1,581 @@ +// +// 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 +// +// 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 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 0) + { + numPolys--; + + for(int i=poly; i= 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= 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= 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 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 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 +// +// 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 List; // Forward declaration... +template class Node +{ + friend class List; + + public: +// Node(void) { next = NULL; } + Node(void): next(NULL) {} +// Node(const T d, Node * ptr = NULL) { data = d; next = ptr; } + Node(const T d, Node * ptr = NULL): data(d), next(ptr) {} + + private: + T data; + Node * next; +}; + +template 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 * 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 List::List(void) +{ + last = NULL; + length = 0; +} + +template List::~List() +{ + while (length) // Destroy all nodes that were created... + { + Node * tmp = last; + last = last->next; + delete tmp; + length--; + } +} + +template bool List::operator==(List &l) +{ + if (Length() != l.Length()) + return false; + + Node * 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 void List::AddAtFront(T data) +{ + Node * newNode = new Node(data); + + if (last == NULL) // i.e., the list is empty... + last = newNode->next = newNode; + else + { + newNode->next = last->next; + last->next = newNode; + } + + length++; +} + +template void List::AddAtRear(T data) +{ + Node * newNode = new Node(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 void List::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 * newNode = new Node(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 T List::GetFront(void) +{ + if (IsEmpty()) + throw LIST_EMPTY; + + T retVal = last->next->data; + Node * ptr = last->next; + + if (length == 1) + last = NULL; + else + last->next = last->next->next; + + delete ptr; + length--; + + return retVal; +} + +template T List::GetRear(void) +{ + if (IsEmpty()) + throw LIST_EMPTY; + + T retVal = last->data; + Node * 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 T List::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 * tmp = last; + + for(int i=1; i!=pos; i++) // Make tmp point to node ahead of del position + tmp = tmp->next; + + Node * nodeToDelete = tmp->next; + T retVal = nodeToDelete->data; + + tmp->next = tmp->next->next; + delete nodeToDelete; + + length--; + return retVal; +} + +template T List::PeekFront(void) +{ + if (IsEmpty()) + throw LIST_EMPTY; + + return last->next->data; +} + +template T List::PeekRear(void) +{ + if (IsEmpty()) + throw LIST_EMPTY; + + return last->data; +} + +template T List::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 * tmp = last; + + for(int i=1; i!=pos; i++) + tmp = tmp->next; + + return tmp->next->data; +} + +template inline bool List::IsEmpty(void) +{ + return (bool)(length == 0); +} + +template inline int List::Length(void) +{ + return length; +} diff --git a/src/registry.cpp b/src/registry.cpp new file mode 100755 index 0000000..cbf3862 --- /dev/null +++ b/src/registry.cpp @@ -0,0 +1,94 @@ +// +// REGISTRY.CPP - Win32 support file +// by James L. Hammons +// (C) 2002 Underground Software +// +// JLH = James Hammons +// +// 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 +#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 diff --git a/src/registry.h b/src/registry.h new file mode 100755 index 0000000..7384341 --- /dev/null +++ b/src/registry.h @@ -0,0 +1,22 @@ +// +// REGISTRY.H - Win32 support file header +// by James L. Hammons +// (C) 2002 Underground Software +// +// JLH = James Hammons +// + +#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__ diff --git a/src/tte_res.h b/src/tte_res.h new file mode 100755 index 0000000..3bf6dba --- /dev/null +++ b/src/tte_res.h @@ -0,0 +1,46 @@ +// +// 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 + diff --git a/src/ttedit.cpp b/src/ttedit.cpp new file mode 100755 index 0000000..cb19ce2 --- /dev/null +++ b/src/ttedit.cpp @@ -0,0 +1,2061 @@ +// +// TTEDIT.CPP - The TrueType Editor +// by James L. Hammons +// (C) 2004 Underground Software +// +// JLH = James L. Hammons +// +// 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 +// + +// 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... + +#include +#include "types.h" +#include "tte_res.h" +#include "ttf.h" +#include "registry.h" +#include "bezier.h" +#include "glyphpoints.h" +#include "vector.h" +#ifdef DEBUG +#include "debug.h" +#endif +#include "ttedit.h" // Usually not necessary, but here we are... +#include +#include +#include + +#include "res/ttedit.xpm" // *nix only, but small enough to not matter +#include "res/toolpal1.xpm" // Docs say this is portable... Let's see! +#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/tool1.xpm" +#include "res/tool2.xpm" +#include "res/tool3.xpm" + +// +// E Q U A T E S +// +#define TOOLSelect 0x00 // The "selection" tool +#define TOOLPolySelect 0x01 // Polygon selection tool +#define TOOLScroll 0x02 // Scroll window tool +#define TOOLZoom 0x03 // Zoom window tool +#define TOOLAddPt 0x04 // Add point tool +#define TOOLAddPoly 0x05 // Polygon creation tool +#define TOOLDelPt 0x06 // Delete point tool +#define TOOLDelPoly 0x07 // Delete polygon tool + +// +// Function and Procedure Prototypes +// +//BOOL CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM); +//void MiscCenterWnd(HWND, HWND); +//bool OnlyOneInstance(void); +void CreateResources(void); +bool Initialization(void); +void DeallocateResources(void); +void SaveAppState(void); +void DrawRoundDot(wxDC &, int32, int32); +void DrawSquareDot(wxDC &, int32, int32); +void DrawRoundDotN(wxDC &, int32, int32, uint32); +void DrawSquareDotN(wxDC &, int32, int32, uint32); +void CreateNewDoc(void); +bool SaveChanges(void); + +// Global constant data + +//const char className[] = "TTEDIT"; +//const char CNCharWin[] = "US_CHARWIN"; +//const char CNToolPal[] = "US_TOOLPALETTE"; +//const char CNStatus[] = "msctls_statusbar32"; +const char filter[] = "Font Files (*.TTF)\0*.TTF\0All Files (*.*)\0*.*\0"; +const char defExt[] = "ttf"; +//const char mtitle[] = "Character Window!"; +const char zoom[] = "Zoom: %u%%"; + +/*const TBBUTTON tbButtons[4] = { + { 0, ID_TBLEFT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }, + { 1, ID_TBRIGHT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }, + { 0, 0, 0, TBSTYLE_SEP, 0, 0 }, + { 2, ID_TBCHARWIN, TBSTATE_ENABLED | TBSTATE_CHECKED, TBSTYLE_CHECK, 0, 0 } +};*/ + + +// +// U N I N I T I A L I Z E D D A T A +// +/* +szSaveChanges SBYTE "Save changes to the following file?", 0Ah, 0Ah +szFile SBYTE MAX_PATH DUP (0) +szWindowName SBYTE (MAX_PATH + 10h) DUP (0) +fScaleFactor REAL4 1.0 // Window scaling factor + +*/ + +//HINSTANCE hInst; +int nCmdShow; +//HWND hMainWnd, hStatusBar, hToolBar, hCharWnd, hToolPalWnd; +char statusBarTxt[64]; +char toolTipTxt[16]; +char strBuf[1024]; + +//HCURSOR hCur[8]; +wxCursor * cur[8]; + +//HBITMAP hBMToolPal1; +//HPEN hRedPen1, hBluePen1, hGreenPen1, hBlackPen1; +//HBRUSH hNullBrush; + +//POINT sizeStamp, sizeTPBM, ptPrevious; +//PTSTRUCT aPts[16]; +//uint32 numPts = 0; +GlyphPoints pts; +int32 ptHighlight = -1, oldPtHighlight = -1, ptNextHighlight = -1, oldPtNextHighlight = -1; +int32 currentTool = TOOLSelect; // Current tool is "selection" tool +bool mouseDown = false; // Mouse down flag +bool NCMouseDown; +//POINT ptWinOffset; +uint32 zoomWndWidth; +bool polyFirstPoint = true; + +char curCharName[] = "Own3d W1nd0w"; // Need to make this a buffer w/default + +//WINDOWPLACEMENT wpM, wpC; +//POINT ptVPM; + + + +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; + + 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); + toolPalette = new ToolWindow(mainFrame, _(""), wxDefaultPosition, wxDefaultSize, + wxNO_BORDER | wxFRAME_NO_TASKBAR); + + return true; +} + +int TTEditApp::OnExit() +{ +#ifdef DEBUG + CloseDebugLog(); +#endif + + return 0; +} + +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()) +{ + // Initialize child subwindow members (and hopefully avoid subtle bugs) + mainWindow = NULL; + + SetIcon(wxICON(ttedit)); +// CreateStatusBar(2); // Create 2 panes + int widths[2] = { -1, 100 }; + 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.0\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) +{ + wxGetApp().toolPalette->Destroy(); + this->Destroy(); +} + +void TTEditFrame::OnCloseWindow(wxCloseEvent &e) +{ + wxGetApp().toolPalette->Destroy(); + this->Destroy(); +} + +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), app(wxGetApp()) +{ + bmp = NULL; + scale = 1.0; + offsetX = offsetY = -10; + + SetCursor(*cur[currentTool]); + 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); + + // Insert your drawing code here. + if (!bmp) + { + bmp = new wxBitmap(field_width * x_cell * X_UNIT + 1, field_height * y_cell * Y_UNIT + 1); + + if (bmp) + { + wxMemoryDC memDC; + memDC.SelectObject(*bmp); + DrawField(&memDC, 0, 0, field_width - 1, field_height - 1); + memDC.SelectObject(wxNullBitmap); + } + } + + if (bmp) + { + wxMemoryDC memDC; + memDC.SelectObject(* bmp); + dc.Blit(0, 0, field_width * x_cell * X_UNIT + 1, field_height * y_cell * Y_UNIT + 1, + &memDC, 0, 0, wxCOPY); + memDC.SelectObject(wxNullBitmap); + } + else + DrawField(&dc, 0, 0, field_width - 1, field_height - 1);*/ + + 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; iFindOrCreatePen(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) && currentTool == 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 (currentTool == 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 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; iMove(pt); + wxGetApp().toolPalette->Show(true); + wxGetApp().toolPalette->SetFocus(); + wxGetApp().toolPalette->CaptureMouse(); + SetCursor(*wxSTANDARD_CURSOR); + } + else if (e.LeftDown()) + { + if (currentTool == TOOLScroll || currentTool == TOOLZoom) + CaptureMouse(); // Make sure we capture the mouse when in scroll/zoom mode + else if (currentTool == 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 (currentTool == 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 (currentTool == TOOLSelect || currentTool == 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 (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); + Refresh(); + } + } + } + else if (e.LeftUp()) + { +// mouseDown = false; + + if (currentTool == TOOLScroll || currentTool == TOOLZoom) +// ReleaseCapture(); + ReleaseMouse(); + } + else if (e.Dragging()) + { +//Do this here? Needed? SetCursor(hCur[currentTool]); + + // 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; + +// if (e.LeftIsDown()) +// { + if (currentTool == TOOLScroll) + { + // 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 if (currentTool == TOOLAddPt || currentTool == TOOLAddPoly || currentTool == TOOLSelect) + { + if (currentTool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch. + { + wxPoint pt2 = GetAdjustedMousePosition(e); + pts.SetXY(ptHighlight, pt2.x, pt2.y); + Refresh(); + } + } + else if (currentTool == 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 (currentTool == TOOLSelect || currentTool == TOOLDelPt || currentTool == TOOLAddPt + || currentTool == TOOLPolySelect)// || currentTool == TOOLAddPoly) + { + wxPoint pt2 = GetAdjustedMousePosition(e); + double closest = 1.0e+99; + + for(int i=0; i 1 && currentTool == TOOLAddPt) + { + double smallest = 1.0e+99; + + for(int i=0; i 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); + +/*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);//*/ + + 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)); +} + +// + +void 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); +} + +// +// 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); +} + + +BEGIN_EVENT_TABLE(CharWindow, wxWindow) +// EVT_PAINT(CharWindow::OnPaint) +// EVT_MOUSE_EVENTS(CharWindow::OnMouseEvent) +END_EVENT_TABLE() + +CharWindow::CharWindow(wxFrame * parent, const wxPoint &pos, const wxSize &size, long style): + wxWindow(parent, -1, pos, size, style) +{ +} + +CharWindow::~CharWindow() +{ +} + + +BEGIN_EVENT_TABLE(ToolWindow, wxWindow) + EVT_PAINT(ToolWindow::OnPaint) + EVT_MOUSE_EVENTS(ToolWindow::OnMouseEvent) +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) +//ToolWindow::ToolWindow(wxFrame * parent, const wxPoint &pos, const wxSize &size, long style): +// wxWindow(parent, -1, pos, size, style) +{ + bmp = new wxBitmap(toolpal1_xpm); + prevTool = -1; + + // Set up sizes + + sizeTPBM.x = bmp->GetWidth(), sizeTPBM.y = bmp->GetHeight(); + sizeStamp.x = sizeTPBM.x / 4, sizeStamp.y = sizeTPBM.y / 2; + + SetSize(10, 10, sizeTPBM.x, sizeTPBM.y); + Show(false); +} + +ToolWindow::~ToolWindow() +{ +} + +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); + + int32 tool = FindSelectedTool(); + + if (tool != -1) + { + //need ul corner of bitmap, ul corner of dest, width/height + wxPoint pt(sizeStamp.x * (tool & 0x03), sizeStamp.y * (tool >> 2)); + dc.Blit(pt.x, pt.y, sizeStamp.x, sizeStamp.y, &memDC, pt.x, pt.y, wxSRC_INVERT); + } + + memDC.SelectObject(wxNullBitmap); +} + +void ToolWindow::OnMouseEvent(wxMouseEvent &e) +{ +// if (e.Moving()) + if (e.Dragging()) + { + int32 tool = FindSelectedTool(); + + if (tool != prevTool) + { + prevTool = tool; + Refresh(false); + } + } + + if (e.RightUp()) + { + int32 tool = FindSelectedTool(), oldTool = currentTool; + + if (tool != -1) + currentTool = tool; + + if (currentTool != TOOLSelect && currentTool != TOOLDelPt && currentTool != TOOLAddPt + && currentTool != TOOLPolySelect) + ptHighlight = -1; + + if (currentTool != oldTool) + Refresh(false); + + if (currentTool == TOOLAddPoly) +#ifdef DEBUGFOO +{ +#endif + polyFirstPoint = true; +#ifdef DEBUGFOO +sprintf(strBuf, "--> Selected poly tool, polyFirstPoint is %s\n", polyFirstPoint ? "true" : "false"); +WriteLogMsg(strBuf); +} +#endif + + ReleaseMouse(); + Show(false); + wxGetApp().mainFrame->mainWindow->SetCursor(*cur[currentTool]); + wxGetApp().mainFrame->mainWindow->SetFocus(); // Make sure the main wnd keeps focus! + } +} + +// +// Find which tool we're pointing at +// Use: xcoord = mouse.x / (bmsize.x/4), ycoord = mouse.y / (bmsize.y/2) +// +int32 ToolWindow::FindSelectedTool(void) +{ + wxPoint pt = ScreenToClient(wxGetMousePosition()); + uint32 x = (uint32)pt.x / sizeStamp.x, y = (uint32)pt.y / sizeStamp.y, tool = (uint32)-1; + + if (x < 4 && y < 2) + tool = (y * 4) + x; + + return tool; +} + + +/* +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 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 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 1 && currentTool == TOOLAddPt) + { + double smallest = 1.0e+99; + + for(int i=0; i 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; +} + +*/ + diff --git a/src/ttedit.h b/src/ttedit.h new file mode 100755 index 0000000..de526f8 --- /dev/null +++ b/src/ttedit.h @@ -0,0 +1,181 @@ +// +// TTEDIT.H: Header file +// +// by James L. Hammons +// (C) 2005 Underground Software +// + +#ifndef __TTEDIT_H__ +#define __TTEDIT_H__ + +#include // 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; + + bool OnInit(); + int OnExit(); +}; + +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); +// void OnEasy(wxCommandEvent &event); +/// void OnMedium(wxCommandEvent &event); +// void OnDifficult(wxCommandEvent &event); + + DECLARE_EVENT_TABLE() +}; + +class TTEditWindow: public wxWindow +{ + private: + TTEditApp & app; // Reference to the application object + double scale; // Window scaling factor + int32 offsetX, offsetY; // Window offsets + + protected: + public: +// int field_width, field_height; +// int x_cell, y_cell; + 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); +// void DrawField(wxDC *, int xc1, int yc1, int xc2, int yc2); +// void Refresh(int xc1, int yc1, int xc2, int yc2); +// void Uncover(int x, int y); +// void UpdateFieldSize(); + + protected: + wxPoint GetAdjustedMousePosition(wxMouseEvent &e); + wxPoint GetAdjustedClientPosition(wxCoord x, wxCoord y); + + DECLARE_EVENT_TABLE() +}; + +class CharWindow: public wxWindow +{ + private: + protected: + public: +// int field_width, field_height; +// int x_cell, y_cell; + wxBitmap * bmp; + + // Constructor and destructor + CharWindow(wxFrame * parent, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0); + ~CharWindow(void); + + void OnPaint(wxPaintEvent &e); + void OnMouseEvent(wxMouseEvent &e); +// void DrawField(wxDC *, int xc1, int yc1, int xc2, int yc2); +// void Refresh(int xc1, int yc1, int xc2, int yc2); +// void Uncover(int x, int y); +// void UpdateFieldSize(); + + DECLARE_EVENT_TABLE() +}; + +class ToolWindow: public wxFrame +//class ToolWindow: public wxWindow +{ + private: + protected: + public: + wxBitmap * bmp; + wxPoint sizeStamp, sizeTPBM; + int prevTool; + + // Constructor and destructor + ToolWindow(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style); +// ToolFrame(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style); +// ToolWindow(wxFrame * parent, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0); + ~ToolWindow(void); + + void OnPaint(wxPaintEvent &e); + void OnMouseEvent(wxMouseEvent &e); +// void DrawField(wxDC *, int xc1, int yc1, int xc2, int yc2); +// void Refresh(int xc1, int yc1, int xc2, int yc2); +// void Uncover(int x, int y); +// void UpdateFieldSize(); + int32 FindSelectedTool(void); + + DECLARE_EVENT_TABLE() +}; + +// Resource/control IDs +/* +#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 */ + +#endif // __TTEDIT_H__ diff --git a/src/ttf.cpp b/src/ttf.cpp new file mode 100755 index 0000000..1244687 --- /dev/null +++ b/src/ttf.cpp @@ -0,0 +1,1212 @@ +// +// 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 +// +// Who When What +// --- ---------- ------------------------------------------------------------- +// JLH ??/??/199? Created this file +// +// +// STILL TO BE DONE: +// +// - Eliminate ALL references to BYTE, WORD, SBYTE, SWORD, etc. +// + +#include // For file handling, etc. // +#include +#include +#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 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= 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 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; im_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= 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; +} + diff --git a/src/ttf.h b/src/ttf.h new file mode 100755 index 0000000..07aac36 --- /dev/null +++ b/src/ttf.h @@ -0,0 +1,296 @@ +// +// 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 +////#include // This is needed only for things like BOOL, etc. +//#include +//#include +//#include // 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 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__ + diff --git a/src/types.h b/src/types.h new file mode 100755 index 0000000..7f589aa --- /dev/null +++ b/src/types.h @@ -0,0 +1,33 @@ +// +// Basic types for platform independent code +// + +#ifndef __TYPES_H__ +#define __TYPES_H__ + +// This is only good on certain intel 32-bit platforms... +// You may need to tweak to suit your specific platform. + +typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned uint32; +typedef signed int32; +//typedef unsigned long long uint64; +//typedef signed long long int64; + +//typedef signed char SBYTE; +//typedef signed short int SWORD; +//typedef signed long int SDWORD; + +/*#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__ diff --git a/src/vector.cpp b/src/vector.cpp new file mode 100755 index 0000000..fc008f3 --- /dev/null +++ b/src/vector.cpp @@ -0,0 +1,141 @@ +// +// VECTOR.H - vector class definition +// +// by James L. Hammons +// (C) 2004 Underground Software +// +// JLH = James L. Hammons +// +// 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 +#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; +} diff --git a/src/vector.h b/src/vector.h new file mode 100755 index 0000000..a7e36ee --- /dev/null +++ b/src/vector.h @@ -0,0 +1,35 @@ +// +// 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__